MemoryManagerSuite.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * uriparser - RFC 3986 URI parsing library
  3. *
  4. * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
  5. * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #undef NDEBUG // because we rely on assert(3) further down
  22. #include <cassert>
  23. #include <cerrno>
  24. #include <cstring> // memcpy
  25. #include <gtest/gtest.h>
  26. #include <uriparser/Uri.h>
  27. // For defaultMemoryManager
  28. extern "C" {
  29. #include "../src/UriMemory.h"
  30. }
  31. namespace {
  32. static void * failingMalloc(UriMemoryManager * memory, size_t size);
  33. static void * failingCalloc(UriMemoryManager * memory, size_t nmemb, size_t size);
  34. static void * failingRealloc(UriMemoryManager * memory, void * ptr, size_t size);
  35. static void * failingReallocarray(UriMemoryManager * memory, void * ptr, size_t nmemb, size_t size);
  36. static void countingFree(UriMemoryManager * memory, void * ptr);
  37. class FailingMemoryManager {
  38. private:
  39. UriMemoryManager memoryManager;
  40. unsigned int callCountAlloc;
  41. unsigned int callCountFree;
  42. unsigned int failAllocAfterTimes;
  43. friend void * failingMalloc(UriMemoryManager * memory, size_t size);
  44. friend void * failingCalloc(UriMemoryManager * memory, size_t nmemb, size_t size);
  45. friend void * failingRealloc(UriMemoryManager * memory, void * ptr, size_t size);
  46. friend void * failingReallocarray(UriMemoryManager * memory, void * ptr, size_t nmemb, size_t size);
  47. friend void countingFree(UriMemoryManager * memory, void * ptr);
  48. public:
  49. FailingMemoryManager(unsigned int failAllocAfterTimes = 0)
  50. : callCountAlloc(0), callCountFree(0),
  51. failAllocAfterTimes(failAllocAfterTimes) {
  52. this->memoryManager.malloc = failingMalloc;
  53. this->memoryManager.calloc = failingCalloc;
  54. this->memoryManager.realloc = failingRealloc;
  55. this->memoryManager.reallocarray = failingReallocarray;
  56. this->memoryManager.free = countingFree;
  57. this->memoryManager.userData = this;
  58. }
  59. UriMemoryManager * operator&() {
  60. return &(this->memoryManager);
  61. }
  62. unsigned int getCallCountFree() const {
  63. return this->callCountFree;
  64. }
  65. };
  66. static void * failingMalloc(UriMemoryManager * memory, size_t size) {
  67. FailingMemoryManager * const fmm = static_cast<FailingMemoryManager *>(memory->userData);
  68. fmm->callCountAlloc++;
  69. if (fmm->callCountAlloc > fmm->failAllocAfterTimes) {
  70. errno = ENOMEM;
  71. return NULL;
  72. }
  73. return malloc(size);
  74. }
  75. static void * failingCalloc(UriMemoryManager * memory, size_t nmemb, size_t size) {
  76. FailingMemoryManager * const fmm = static_cast<FailingMemoryManager *>(memory->userData);
  77. fmm->callCountAlloc++;
  78. if (fmm->callCountAlloc > fmm->failAllocAfterTimes) {
  79. errno = ENOMEM;
  80. return NULL;
  81. }
  82. return calloc(nmemb, size);
  83. }
  84. static void * failingRealloc(UriMemoryManager * memory, void * ptr, size_t size) {
  85. FailingMemoryManager * const fmm = static_cast<FailingMemoryManager *>(memory->userData);
  86. fmm->callCountAlloc++;
  87. if (fmm->callCountAlloc > fmm->failAllocAfterTimes) {
  88. errno = ENOMEM;
  89. return NULL;
  90. }
  91. return realloc(ptr, size);
  92. }
  93. static void * failingReallocarray(UriMemoryManager * memory, void * ptr, size_t nmemb, size_t size) {
  94. return uriEmulateReallocarray(memory, ptr, nmemb, size);
  95. }
  96. static void countingFree(UriMemoryManager * memory, void * ptr) {
  97. FailingMemoryManager * const fmm = static_cast<FailingMemoryManager *>(memory->userData);
  98. fmm->callCountFree++;
  99. return free(ptr);
  100. }
  101. static UriUriA parse(const char * sourceUriString) {
  102. UriParserStateA state;
  103. UriUriA uri;
  104. state.uri = &uri;
  105. assert(uriParseUriA(&state, sourceUriString) == URI_SUCCESS);
  106. return uri;
  107. }
  108. static UriQueryListA * parseQueryList(const char * queryString) {
  109. UriQueryListA * queryList;
  110. const char * const first = queryString;
  111. const char * const afterLast = first + strlen(first);
  112. assert(uriDissectQueryMallocA(&queryList, NULL, first, afterLast)
  113. == URI_SUCCESS);
  114. return queryList;
  115. }
  116. } // namespace
  117. TEST(MemoryManagerCompletenessSuite, AllFunctionMembersRequired) {
  118. UriUriA uri = parse("whatever");
  119. UriMemoryManager memory;
  120. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  121. memory.malloc = NULL;
  122. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory),
  123. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  124. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  125. memory.calloc = NULL;
  126. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory),
  127. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  128. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  129. memory.realloc = NULL;
  130. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory),
  131. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  132. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  133. memory.reallocarray = NULL;
  134. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory),
  135. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  136. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  137. memory.free = NULL;
  138. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory),
  139. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  140. memcpy(&memory, &defaultMemoryManager, sizeof(UriMemoryManager));
  141. ASSERT_EQ(uriFreeUriMembersMmA(&uri, &memory), URI_SUCCESS);
  142. }
  143. TEST(MemoryManagerCompletenessSuite, MallocAndFreeRequiredOnly) {
  144. UriMemoryManager memory;
  145. UriMemoryManager backend;
  146. memcpy(&backend, &defaultMemoryManager, sizeof(UriMemoryManager));
  147. backend.malloc = NULL;
  148. ASSERT_EQ(uriCompleteMemoryManager(&memory, &backend),
  149. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  150. memcpy(&backend, &defaultMemoryManager, sizeof(UriMemoryManager));
  151. backend.free = NULL;
  152. ASSERT_EQ(uriCompleteMemoryManager(&memory, &backend),
  153. URI_ERROR_MEMORY_MANAGER_INCOMPLETE);
  154. }
  155. TEST(MemoryManagerTestingSuite, DISABLED_DefaultMemoryManager) {
  156. ASSERT_EQ(uriTestMemoryManager(&defaultMemoryManager), URI_SUCCESS);
  157. }
  158. TEST(MemoryManagerTestingSuite, CompleteMemoryManager) {
  159. UriMemoryManager memory;
  160. UriMemoryManager backend;
  161. memset(&backend, 0, sizeof(UriMemoryManager));
  162. backend.malloc = defaultMemoryManager.malloc;
  163. backend.free = defaultMemoryManager.free;
  164. ASSERT_EQ(uriCompleteMemoryManager(&memory, &backend),
  165. URI_SUCCESS);
  166. ASSERT_EQ(uriTestMemoryManager(&memory), URI_SUCCESS);
  167. }
  168. TEST(MemoryManagerTestingSuite, DISABLED_EmulateCalloc) {
  169. UriMemoryManager partialEmulationMemoryManager;
  170. memcpy(&partialEmulationMemoryManager, &defaultMemoryManager,
  171. sizeof(UriMemoryManager));
  172. partialEmulationMemoryManager.calloc = uriEmulateCalloc;
  173. ASSERT_EQ(uriTestMemoryManager(&partialEmulationMemoryManager),
  174. URI_SUCCESS);
  175. }
  176. TEST(MemoryManagerTestingSuite, EmulateReallocarray) {
  177. UriMemoryManager partialEmulationMemoryManager;
  178. memcpy(&partialEmulationMemoryManager, &defaultMemoryManager,
  179. sizeof(UriMemoryManager));
  180. partialEmulationMemoryManager.reallocarray = uriEmulateReallocarray;
  181. ASSERT_EQ(uriTestMemoryManager(&partialEmulationMemoryManager),
  182. URI_SUCCESS);
  183. }
  184. TEST(MemoryManagerTestingOverflowDetectionSuite, EmulateCalloc) {
  185. EXPECT_GT(2 * sizeof(size_t), sizeof(void *));
  186. errno = 0;
  187. ASSERT_EQ(NULL, uriEmulateCalloc(
  188. &defaultMemoryManager, (size_t)-1, (size_t)-1));
  189. ASSERT_EQ(errno, ENOMEM);
  190. }
  191. TEST(MemoryManagerTestingOverflowDetectionSuite, EmulateReallocarray) {
  192. EXPECT_GT(2 * sizeof(size_t), sizeof(void *));
  193. errno = 0;
  194. ASSERT_EQ(NULL, uriEmulateReallocarray(
  195. &defaultMemoryManager, NULL, (size_t)-1, (size_t)-1));
  196. ASSERT_EQ(errno, ENOMEM);
  197. }
  198. TEST(MemoryManagerTestingSuite, EmulateCallocAndReallocarray) {
  199. UriMemoryManager partialEmulationMemoryManager;
  200. memcpy(&partialEmulationMemoryManager, &defaultMemoryManager,
  201. sizeof(UriMemoryManager));
  202. partialEmulationMemoryManager.calloc = uriEmulateCalloc;
  203. partialEmulationMemoryManager.reallocarray = uriEmulateReallocarray;
  204. ASSERT_EQ(uriTestMemoryManager(&partialEmulationMemoryManager),
  205. URI_SUCCESS);
  206. }
  207. TEST(FailingMemoryManagerSuite, AddBaseUriExMm) {
  208. UriUriA absoluteDest;
  209. UriUriA relativeSource = parse("foo");
  210. UriUriA absoluteBase = parse("http://example.org/bar");
  211. const UriResolutionOptions options = URI_RESOLVE_STRICTLY;
  212. FailingMemoryManager failingMemoryManager;
  213. ASSERT_EQ(uriAddBaseUriExMmA(&absoluteDest, &relativeSource,
  214. &absoluteBase, options, &failingMemoryManager),
  215. URI_ERROR_MALLOC);
  216. uriFreeUriMembersA(&relativeSource);
  217. uriFreeUriMembersA(&absoluteBase);
  218. }
  219. TEST(FailingMemoryManagerSuite, ComposeQueryMallocExMm) {
  220. char * dest = NULL;
  221. UriQueryListA * const queryList = parseQueryList("k1=v1");
  222. UriBool spaceToPlus = URI_TRUE; // not of interest
  223. UriBool normalizeBreaks = URI_TRUE; // not of interest
  224. FailingMemoryManager failingMemoryManager;
  225. ASSERT_EQ(uriComposeQueryMallocExMmA(&dest, queryList,
  226. spaceToPlus, normalizeBreaks, &failingMemoryManager),
  227. URI_ERROR_MALLOC);
  228. uriFreeQueryListA(queryList);
  229. }
  230. TEST(FailingMemoryManagerSuite, DissectQueryMallocExMm) {
  231. UriQueryListA * queryList;
  232. int itemCount;
  233. const char * const first = "k1=v1&k2=v2";
  234. const char * const afterLast = first + strlen(first);
  235. const UriBool plusToSpace = URI_TRUE; // not of interest
  236. const UriBreakConversion breakConversion = URI_BR_DONT_TOUCH; // not o. i.
  237. FailingMemoryManager failingMemoryManager;
  238. ASSERT_EQ(uriDissectQueryMallocExMmA(&queryList, &itemCount,
  239. first, afterLast, plusToSpace, breakConversion,
  240. &failingMemoryManager),
  241. URI_ERROR_MALLOC);
  242. }
  243. TEST(FailingMemoryManagerSuite, FreeQueryListMm) {
  244. UriQueryListA * const queryList = parseQueryList("k1=v1");
  245. FailingMemoryManager failingMemoryManager;
  246. ASSERT_EQ(failingMemoryManager.getCallCountFree(), 0U);
  247. uriFreeQueryListMmA(queryList, &failingMemoryManager);
  248. ASSERT_GE(failingMemoryManager.getCallCountFree(), 1U);
  249. }
  250. TEST(FailingMemoryManagerSuite, FreeUriMembersMm) {
  251. UriUriA uri = parse("http://example.org/");
  252. FailingMemoryManager failingMemoryManager;
  253. ASSERT_EQ(failingMemoryManager.getCallCountFree(), 0U);
  254. uriFreeUriMembersMmA(&uri, &failingMemoryManager);
  255. ASSERT_GE(failingMemoryManager.getCallCountFree(), 1U);
  256. uriFreeUriMembersA(&uri);
  257. }
  258. namespace {
  259. void testNormalizeSyntaxWithFailingMallocCallsFreeTimes(const char * uriString,
  260. unsigned int mask,
  261. unsigned int failAllocAfterTimes = 0,
  262. unsigned int expectedCallCountFree = 0) {
  263. UriUriA uri = parse(uriString);
  264. FailingMemoryManager failingMemoryManager(failAllocAfterTimes);
  265. ASSERT_EQ(uriNormalizeSyntaxExMmA(&uri, mask, &failingMemoryManager),
  266. URI_ERROR_MALLOC);
  267. EXPECT_EQ(failingMemoryManager.getCallCountFree(), expectedCallCountFree);
  268. uriFreeUriMembersA(&uri);
  269. }
  270. } // namespace
  271. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmScheme) {
  272. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("hTTp://example.org/path", URI_NORMALIZE_SCHEME);
  273. }
  274. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmEmptyUserInfo) {
  275. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//@:123", URI_NORMALIZE_USER_INFO);
  276. }
  277. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmEmptyHostRegname) {
  278. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//:123", URI_NORMALIZE_HOST);
  279. }
  280. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmEmptyQuery) {
  281. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//:123?", URI_NORMALIZE_QUERY);
  282. }
  283. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmEmptyFragment) {
  284. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//:123#", URI_NORMALIZE_FRAGMENT);
  285. }
  286. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmHostTextIp4) { // issue #121
  287. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//192.0.2.0:123" /* RFC 5737 */, URI_NORMALIZE_HOST, 1, 1);
  288. }
  289. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmHostTextIp6) { // issue #121
  290. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//[2001:db8::]:123" /* RFC 3849 */, URI_NORMALIZE_HOST, 1, 1);
  291. }
  292. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmHostTextRegname) { // issue #121
  293. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//host123.test:123" /* RFC 6761 */, URI_NORMALIZE_HOST, 1, 1);
  294. }
  295. TEST(FailingMemoryManagerSuite, NormalizeSyntaxExMmHostTextFuture) { // issue #121
  296. testNormalizeSyntaxWithFailingMallocCallsFreeTimes("//[v7.X]:123" /* arbitrary IPvFuture */, URI_NORMALIZE_HOST, 1, 1);
  297. }
  298. TEST(FailingMemoryManagerSuite, ParseSingleUriExMm) {
  299. UriUriA uri;
  300. const char * const first = "k1=v1&k2=v2";
  301. const char * const afterLast = first + strlen(first);
  302. FailingMemoryManager failingMemoryManager;
  303. ASSERT_EQ(uriParseSingleUriExMmA(&uri, first, afterLast, NULL,
  304. &failingMemoryManager),
  305. URI_ERROR_MALLOC);
  306. }
  307. TEST(FailingMemoryManagerSuite, RemoveBaseUriMm) {
  308. UriUriA dest;
  309. UriUriA absoluteSource = parse("http://example.org/a/b/c/");
  310. UriUriA absoluteBase = parse("http://example.org/a/");
  311. const UriBool domainRootMode = URI_TRUE; // not of interest
  312. FailingMemoryManager failingMemoryManager;
  313. ASSERT_EQ(uriRemoveBaseUriMmA(&dest, &absoluteSource, &absoluteBase,
  314. domainRootMode, &failingMemoryManager),
  315. URI_ERROR_MALLOC);
  316. uriFreeUriMembersA(&absoluteSource);
  317. uriFreeUriMembersA(&absoluteBase);
  318. }