diff options
| author | Jörg Frings-Fürst <debian@jff-webhsoting.net> | 2018-11-16 07:16:51 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhsoting.net> | 2018-11-16 07:16:51 +0100 | 
| commit | cd9c1ea3e9c54da1a211563736d6f84664058da8 (patch) | |
| tree | f1d883b562a669deb6bfd59b4de27bfaaa63d8a5 /src | |
| parent | 71a38df59b7b10358477073c9bc053055aa394ce (diff) | |
| parent | 5ef83547e904e4d411239ea0a27571e7d1a0b5b4 (diff) | |
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'src')
| -rw-r--r-- | src/UriCommon.c | 77 | ||||
| -rw-r--r-- | src/UriCommon.h | 19 | ||||
| -rw-r--r-- | src/UriMemory.c | 470 | ||||
| -rw-r--r-- | src/UriMemory.h | 59 | ||||
| -rw-r--r-- | src/UriNormalize.c | 165 | ||||
| -rw-r--r-- | src/UriParse.c | 691 | ||||
| -rw-r--r-- | src/UriQuery.c | 107 | ||||
| -rw-r--r-- | src/UriResolve.c | 69 | ||||
| -rw-r--r-- | src/UriShorten.c | 48 | 
9 files changed, 1252 insertions, 453 deletions
| diff --git a/src/UriCommon.c b/src/UriCommon.c index 571d6d4..039beda 100644 --- a/src/UriCommon.c +++ b/src/UriCommon.c @@ -75,6 +75,9 @@  void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) { +	if (uri == NULL) { +		return; +	}  	memset(uri, 0, sizeof(URI_TYPE(Uri)));  } @@ -118,17 +121,17 @@ int URI_FUNC(CompareRange)(  /* Properly removes "." and ".." path segments */  UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, -		UriBool relative) { +		UriBool relative, UriMemoryManager * memory) {  	if (uri == NULL) {  		return URI_TRUE;  	} -	return URI_FUNC(RemoveDotSegmentsEx)(uri, relative, uri->owner); +	return URI_FUNC(RemoveDotSegmentsEx)(uri, relative, uri->owner, memory);  }  UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, -        UriBool relative, UriBool pathOwned) { +		UriBool relative, UriBool pathOwned, UriMemoryManager * memory) {  	URI_TYPE(PathSegment) * walker;  	if ((uri == NULL) || (uri->pathHead == NULL)) {  		return URI_TRUE; @@ -173,13 +176,13 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  						}  						if (pathOwned && (walker->text.first != walker->text.afterLast)) { -							free((URI_CHAR *)walker->text.first); +							memory->free(memory, (URI_CHAR *)walker->text.first);  						} -						free(walker); +						memory->free(memory, walker);  					} else {  						/* Last segment */  						if (pathOwned && (walker->text.first != walker->text.afterLast)) { -							free((URI_CHAR *)walker->text.first); +							memory->free(memory, (URI_CHAR *)walker->text.first);  						}  						if (prev == NULL) { @@ -189,7 +192,7 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  								walker->text.first = URI_FUNC(SafeToPointTo);  								walker->text.afterLast = URI_FUNC(SafeToPointTo);  							} else { -								free(walker); +								memory->free(memory, walker);  								uri->pathHead = NULL;  								uri->pathTail = NULL; @@ -237,21 +240,20 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  								walker->next->reserved = prevPrev;  							} else {  								/* Last segment -> insert "" segment to represent trailing slash, update tail */ -								URI_TYPE(PathSegment) * const segment = malloc(1 * sizeof(URI_TYPE(PathSegment))); +								URI_TYPE(PathSegment) * const segment = memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment)));  								if (segment == NULL) {  									if (pathOwned && (walker->text.first != walker->text.afterLast)) { -										free((URI_CHAR *)walker->text.first); +										memory->free(memory, (URI_CHAR *)walker->text.first);  									} -									free(walker); +									memory->free(memory, walker);  									if (pathOwned && (prev->text.first != prev->text.afterLast)) { -										free((URI_CHAR *)prev->text.first); +										memory->free(memory, (URI_CHAR *)prev->text.first);  									} -									free(prev); +									memory->free(memory, prev);  									return URI_FALSE; /* Raises malloc error */  								} -								memset(segment, 0, sizeof(URI_TYPE(PathSegment)));  								segment->text.first = URI_FUNC(SafeToPointTo);  								segment->text.afterLast = URI_FUNC(SafeToPointTo);  								prevPrev->next = segment; @@ -259,14 +261,14 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  							}  							if (pathOwned && (walker->text.first != walker->text.afterLast)) { -								free((URI_CHAR *)walker->text.first); +								memory->free(memory, (URI_CHAR *)walker->text.first);  							} -							free(walker); +							memory->free(memory, walker);  							if (pathOwned && (prev->text.first != prev->text.afterLast)) { -								free((URI_CHAR *)prev->text.first); +								memory->free(memory, (URI_CHAR *)prev->text.first);  							} -							free(prev); +							memory->free(memory, prev);  							walker = nextBackup;  						} else { @@ -276,14 +278,14 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  								walker->next->reserved = NULL;  								if (pathOwned && (walker->text.first != walker->text.afterLast)) { -									free((URI_CHAR *)walker->text.first); +									memory->free(memory, (URI_CHAR *)walker->text.first);  								} -								free(walker); +								memory->free(memory, walker);  							} else {  								/* Re-use segment for "" path segment to represent trailing slash, update tail */  								URI_TYPE(PathSegment) * const segment = walker;  								if (pathOwned && (segment->text.first != segment->text.afterLast)) { -									free((URI_CHAR *)segment->text.first); +									memory->free(memory, (URI_CHAR *)segment->text.first);  								}  								segment->text.first = URI_FUNC(SafeToPointTo);  								segment->text.afterLast = URI_FUNC(SafeToPointTo); @@ -292,9 +294,9 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  							}  							if (pathOwned && (prev->text.first != prev->text.afterLast)) { -								free((URI_CHAR *)prev->text.first); +								memory->free(memory, (URI_CHAR *)prev->text.first);  							} -							free(prev); +							memory->free(memory, prev);  							walker = nextBackup;  						} @@ -310,9 +312,9 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  						}  						if (pathOwned && (walker->text.first != walker->text.afterLast)) { -							free((URI_CHAR *)walker->text.first); +							memory->free(memory, (URI_CHAR *)walker->text.first);  						} -						free(walker); +						memory->free(memory, walker);  						walker = anotherNextBackup;  					} @@ -339,9 +341,10 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,  /* Properly removes "." and ".." path segments */ -UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri) { +UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, +		UriMemoryManager * memory) {  	const UriBool ABSOLUTE = URI_FALSE; -	return URI_FUNC(RemoveDotSegments)(uri, ABSOLUTE); +	return URI_FUNC(RemoveDotSegments)(uri, ABSOLUTE, memory);  } @@ -429,7 +432,7 @@ UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) {  /* Copies the path segment list from one URI to another. */  UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, -		const URI_TYPE(Uri) * source) { +		const URI_TYPE(Uri) * source, UriMemoryManager * memory) {  	if (source->pathHead == NULL) {  		/* No path component */  		dest->pathHead = NULL; @@ -439,7 +442,7 @@ UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest,  		URI_TYPE(PathSegment) * sourceWalker = source->pathHead;  		URI_TYPE(PathSegment) * destPrev = NULL;  		do { -			URI_TYPE(PathSegment) * cur = malloc(sizeof(URI_TYPE(PathSegment))); +			URI_TYPE(PathSegment) * cur = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));  			if (cur == NULL) {  				/* Fix broken list */  				if (destPrev != NULL) { @@ -472,10 +475,10 @@ UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest,  /* Copies the authority part of an URI over to another. */  UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, -		const URI_TYPE(Uri) * source) { +		const URI_TYPE(Uri) * source, UriMemoryManager * memory) {  	/* From this functions usage we know that *  	 * the dest URI cannot be uri->owner      */ - +	  	/* Copy userInfo */  	dest->userInfo = source->userInfo; @@ -484,7 +487,7 @@ UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,  	/* Copy hostData */  	if (source->hostData.ip4 != NULL) { -		dest->hostData.ip4 = malloc(sizeof(UriIp4)); +		dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4));  		if (dest->hostData.ip4 == NULL) {  			return URI_FALSE; /* Raises malloc error */  		} @@ -494,7 +497,7 @@ UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,  		dest->hostData.ipFuture.afterLast = NULL;  	} else if (source->hostData.ip6 != NULL) {  		dest->hostData.ip4 = NULL; -		dest->hostData.ip6 = malloc(sizeof(UriIp6)); +		dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6));  		if (dest->hostData.ip6 == NULL) {  			return URI_FALSE; /* Raises malloc error */  		} @@ -515,7 +518,8 @@ UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, -UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) { +UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, +		UriMemoryManager * memory) {  	URI_TYPE(PathSegment) * segment;  	if (	/* Case 1: absolute path, empty first segment */ @@ -534,7 +538,7 @@ UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) {  		return URI_TRUE;  	} -	segment = malloc(1 * sizeof(URI_TYPE(PathSegment))); +	segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));  	if (segment == NULL) {  		return URI_FALSE; /* Raises malloc error */  	} @@ -549,14 +553,15 @@ UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) { -void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri) { +void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, +		UriMemoryManager * memory) {  	/* Fix path if only one empty segment */  	if (!uri->absolutePath  			&& !URI_FUNC(IsHostSet)(uri)  			&& (uri->pathHead != NULL)  			&& (uri->pathHead->next == NULL)  			&& (uri->pathHead->text.first == uri->pathHead->text.afterLast)) { -		free(uri->pathHead); +		memory->free(memory, uri->pathHead);  		uri->pathHead = NULL;  		uri->pathTail = NULL;  	} diff --git a/src/UriCommon.h b/src/UriCommon.h index b062fcc..916055c 100644 --- a/src/UriCommon.h +++ b/src/UriCommon.h @@ -82,10 +82,12 @@ int URI_FUNC(CompareRange)(  		const URI_TYPE(TextRange) * a,  		const URI_TYPE(TextRange) * b); -UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri); -UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, UriBool relative); +UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, +		UriMemoryManager * memory); +UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, UriBool relative, +		UriMemoryManager * memory);  UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, -        UriBool relative, UriBool pathOwned); +		UriBool relative, UriBool pathOwned, UriMemoryManager * memory);  unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig);  URI_CHAR URI_FUNC(HexToLetter)(unsigned int value); @@ -93,11 +95,14 @@ URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase);  UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri); -UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source); -UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source); +UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source, +		UriMemoryManager * memory); +UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, +		const URI_TYPE(Uri) * source, UriMemoryManager * memory); -UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri); -void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri); +UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); +void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, +		UriMemoryManager * memory);  #endif diff --git a/src/UriMemory.c b/src/UriMemory.c new file mode 100644 index 0000000..5e6bcc4 --- /dev/null +++ b/src/UriMemory.c @@ -0,0 +1,470 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2018, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org> + * All rights reserved. + * + * Redistribution  and use in source and binary forms, with or without + * modification,  are permitted provided that the following conditions + * are met: + * + *     * Redistributions   of  source  code  must  retain  the   above + *       copyright  notice, this list of conditions and the  following + *       disclaimer. + * + *     * Redistributions  in  binary  form must  reproduce  the  above + *       copyright  notice, this list of conditions and the  following + *       disclaimer   in  the  documentation  and/or  other  materials + *       provided with the distribution. + * + *     * Neither  the name of the <ORGANIZATION> nor the names of  its + *       contributors  may  be  used to endorse  or  promote  products + *       derived  from  this software without specific  prior  written + *       permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT + * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS + * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES + * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriMemory.c + * Holds memory manager implementation. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if HAVE_REALLOCARRAY +# ifndef _GNU_SOURCE +#  define _GNU_SOURCE 1 +# endif +#endif + +#include <errno.h> +#include <stdlib.h> + + + +#ifndef URI_DOXYGEN +# include "UriMemory.h" +#endif + + + +#define URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size) \ +		do { \ +			/* check for unsigned overflow */ \ +			if ((nmemb != 0) && (total_size / nmemb != size)) { \ +				errno = ENOMEM; \ +				return NULL; \ +			} \ +		} while (0) + + + +static void * uriDefaultMalloc(UriMemoryManager * URI_UNUSED(memory), +		size_t size) { +	return malloc(size); +} + + + +static void * uriDefaultCalloc(UriMemoryManager * URI_UNUSED(memory), +		size_t nmemb, size_t size) { +	return calloc(nmemb, size); +} + + + +static void * uriDefaultRealloc(UriMemoryManager * URI_UNUSED(memory), +		void * ptr, size_t size) { +	return realloc(ptr, size); +} + + + +static void * uriDefaultReallocarray(UriMemoryManager * URI_UNUSED(memory), +		void * ptr, size_t nmemb, size_t size) { +#if HAVE_REALLOCARRAY +	return reallocarray(ptr, nmemb, size); +#else +	const size_t total_size = nmemb * size; + +	URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size);  /* may return */ + +	return realloc(ptr, total_size); +#endif +} + + + +static void uriDefaultFree(UriMemoryManager * URI_UNUSED(memory), +		void * ptr) { +	free(ptr); +} + + + +UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory) { +	return (memory +			&& memory->malloc +			&& memory->calloc +			&& memory->realloc +			&& memory->reallocarray +			&& memory->free) ? URI_TRUE : URI_FALSE; +} + + + +void * uriEmulateCalloc(UriMemoryManager * memory, size_t nmemb, size_t size) { +	void * buffer; +	const size_t total_size = nmemb * size; + +	if (memory == NULL) { +		errno = EINVAL; +		return NULL; +	} + +	URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size);  /* may return */ + +	buffer = memory->malloc(memory, total_size); +	if (buffer == NULL) { +		/* errno set by malloc */ +		return NULL; +	} +	memset(buffer, 0, total_size); +	return buffer; +} + + + +void * uriEmulateReallocarray(UriMemoryManager * memory, +		void * ptr, size_t nmemb, size_t size) { +	const size_t total_size = nmemb * size; + +	if (memory == NULL) { +		errno = EINVAL; +		return NULL; +	} + +	URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size);  /* may return */ + +	return memory->realloc(memory, ptr, total_size); +} + + + +static void * uriDecorateMalloc(UriMemoryManager * memory, +		size_t size) { +	UriMemoryManager * backend; +	const size_t extraBytes = sizeof(size_t); +	void * buffer; + +	if (memory == NULL) { +		errno = EINVAL; +		return NULL; +	} + +	/* check for unsigned overflow */ +	if (size > ((size_t)-1) - extraBytes) { +		errno = ENOMEM; +		return NULL; +	} + +	backend = (UriMemoryManager *)memory->userData; +	if (backend == NULL) { +		errno = EINVAL; +		return NULL; +	} + +	buffer = backend->malloc(backend, extraBytes + size); +	if (buffer == NULL) { +		return NULL; +	} + +	*(size_t *)buffer = size; + +	return (char *)buffer + extraBytes; +} + + + +static void * uriDecorateRealloc(UriMemoryManager * memory, +		void * ptr, size_t size) { +	void * newBuffer; +	size_t prevSize; + +	if (memory == NULL) { +		errno = EINVAL; +		return NULL; +	} + +	/* man realloc: "If ptr is NULL, then the call is equivalent to +	 * malloc(size), for *all* values of size" */ +	if (ptr == NULL) { +		return memory->malloc(memory, size); +	} + +	/* man realloc: "If size is equal to zero, and ptr is *not* NULL, +	 * then the call is equivalent to free(ptr)." */ +	if (size == 0) { +		memory->free(memory, ptr); +		return NULL; +	} + +	prevSize = *((size_t *)((char *)ptr - sizeof(size_t))); + +	/* Anything to do? */ +	if (size <= prevSize) { +		return ptr; +	} + +	newBuffer = memory->malloc(memory, size); +	if (newBuffer == NULL) { +		/* errno set by malloc */ +		return NULL; +	} + +	memcpy(newBuffer, ptr, prevSize); + +	memory->free(memory, ptr); + +	return newBuffer; +} + + + +static void uriDecorateFree(UriMemoryManager * memory, void * ptr) { +	UriMemoryManager * backend; + +	if ((ptr == NULL) || (memory == NULL)) { +		return; +	} + +	backend = (UriMemoryManager *)memory->userData; +	if (backend == NULL) { +		return; +	} + +	backend->free(backend, (char *)ptr - sizeof(size_t)); +} + + + +int uriCompleteMemoryManager(UriMemoryManager * memory, +		UriMemoryManager * backend) { +	if ((memory == NULL) || (backend == NULL)) { +		return URI_ERROR_NULL; +	} + +	if ((backend->malloc == NULL) || (backend->free == NULL)) { +		return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; +	} + +	memory->calloc = uriEmulateCalloc; +	memory->reallocarray = uriEmulateReallocarray; + +	memory->malloc = uriDecorateMalloc; +	memory->realloc = uriDecorateRealloc; +	memory->free = uriDecorateFree; + +	memory->userData = backend; + +	return URI_SUCCESS; +} + + + +int uriTestMemoryManager(UriMemoryManager * memory) { +	const size_t mallocSize = 7; +	const size_t callocNmemb = 3; +	const size_t callocSize = 5; +	const size_t callocTotalSize = callocNmemb * callocSize; +	const size_t reallocSize = 11; +	const size_t reallocarrayNmemb = 5; +	const size_t reallocarraySize = 7; +	const size_t reallocarrayTotal = reallocarrayNmemb * reallocarraySize; +	size_t index; +	char * buffer; + +	if (memory == NULL) { +		return URI_ERROR_NULL; +	} + +	if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { +		return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; +	} + +	/* malloc + free*/ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xF1'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* calloc + free */ +	buffer = memory->calloc(memory, callocNmemb, callocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	for (index = 0; index < callocTotalSize; index++) {  /* all zeros? */ +		if (buffer[index] != '\0') { +			return URI_ERROR_MEMORY_MANAGER_FAULTY; +		} +	} +	buffer[callocTotalSize - 1] = '\xF2'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* malloc + realloc + free */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	for (index = 0; index < mallocSize; index++) { +		buffer[index] = '\xF3'; +	} +	buffer = memory->realloc(memory, buffer, reallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	for (index = 0; index < mallocSize; index++) {  /* previous content? */ +		if (buffer[index] != '\xF3') { +			return URI_ERROR_MEMORY_MANAGER_FAULTY; +		} +	} +	buffer[reallocSize - 1] = '\xF4'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* malloc + realloc ptr!=NULL size==0 (equals free) */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xF5'; +	memory->realloc(memory, buffer, 0); +	buffer = NULL; + +	/* realloc ptr==NULL size!=0 (equals malloc) + free */ +	buffer = memory->realloc(memory, NULL, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xF6'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* realloc ptr==NULL size==0 (equals malloc) + free */ +	buffer = memory->realloc(memory, NULL, 0); +	if (buffer != NULL) { +		memory->free(memory, buffer); +		buffer = NULL; +	} + +	/* malloc + reallocarray + free */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	for (index = 0; index < mallocSize; index++) { +		buffer[index] = '\xF7'; +	} +	buffer = memory->reallocarray(memory, buffer, reallocarrayNmemb, +			reallocarraySize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	for (index = 0; index < mallocSize; index++) {  /* previous content? */ +		if (buffer[index] != '\xF7') { +			return URI_ERROR_MEMORY_MANAGER_FAULTY; +		} +	} +	buffer[reallocarrayTotal - 1] = '\xF8'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* malloc + reallocarray ptr!=NULL nmemb==0 size!=0 (equals free) */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xF9'; +	memory->reallocarray(memory, buffer, 0, reallocarraySize); +	buffer = NULL; + +	/* malloc + reallocarray ptr!=NULL nmemb!=0 size==0 (equals free) */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xFA'; +	memory->reallocarray(memory, buffer, reallocarrayNmemb, 0); +	buffer = NULL; + +	/* malloc + reallocarray ptr!=NULL nmemb==0 size==0 (equals free) */ +	buffer = memory->malloc(memory, mallocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[mallocSize - 1] = '\xFB'; +	memory->reallocarray(memory, buffer, 0, 0); +	buffer = NULL; + +	/* reallocarray ptr==NULL nmemb!=0 size!=0 (equals malloc) + free */ +	buffer = memory->reallocarray(memory, NULL, callocNmemb, callocSize); +	if (buffer == NULL) { +		return URI_ERROR_MEMORY_MANAGER_FAULTY; +	} +	buffer[callocTotalSize - 1] = '\xFC'; +	memory->free(memory, buffer); +	buffer = NULL; + +	/* reallocarray ptr==NULL nmemb==0 size!=0 (equals malloc) + free */ +	buffer = memory->reallocarray(memory, NULL, 0, callocSize); +	if (buffer != NULL) { +		memory->free(memory, buffer); +		buffer = NULL; +	} + +	/* reallocarray ptr==NULL nmemb!=0 size==0 (equals malloc) + free */ +	buffer = memory->reallocarray(memory, NULL, callocNmemb, 0); +	if (buffer != NULL) { +		memory->free(memory, buffer); +		buffer = NULL; +	} + +	/* reallocarray ptr==NULL nmemb==0 size==0 (equals malloc) + free */ +	buffer = memory->reallocarray(memory, NULL, 0, 0); +	if (buffer != NULL) { +		memory->free(memory, buffer); +		buffer = NULL; +	} + +	return URI_SUCCESS; +} + + + +/*extern*/ UriMemoryManager defaultMemoryManager = { +	uriDefaultMalloc, +	uriDefaultCalloc, +	uriDefaultRealloc, +	uriDefaultReallocarray, +	uriDefaultFree, +	NULL  /* userData */ +}; diff --git a/src/UriMemory.h b/src/UriMemory.h new file mode 100644 index 0000000..c40c072 --- /dev/null +++ b/src/UriMemory.h @@ -0,0 +1,59 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2018, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org> + * All rights reserved. + * + * Redistribution  and use in source and binary forms, with or without + * modification,  are permitted provided that the following conditions + * are met: + * + *     * Redistributions   of  source  code  must  retain  the   above + *       copyright  notice, this list of conditions and the  following + *       disclaimer. + * + *     * Redistributions  in  binary  form must  reproduce  the  above + *       copyright  notice, this list of conditions and the  following + *       disclaimer   in  the  documentation  and/or  other  materials + *       provided with the distribution. + * + *     * Neither  the name of the <ORGANIZATION> nor the names of  its + *       contributors  may  be  used to endorse  or  promote  products + *       derived  from  this software without specific  prior  written + *       permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT + * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS + * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES + * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef URI_DOXYGEN +# include <uriparser/Uri.h> +#endif + + + +#define URI_CHECK_MEMORY_MANAGER(memory)  \ +	do { \ +		if (memory == NULL) { \ +			memory = &defaultMemoryManager; \ +		} else if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { \ +			return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; \ +		} \ +	} while (0) + + + +extern UriMemoryManager defaultMemoryManager; + +UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory); diff --git a/src/UriNormalize.c b/src/UriNormalize.c index d68c371..0e798c0 100644 --- a/src/UriNormalize.c +++ b/src/UriNormalize.c @@ -71,22 +71,28 @@  # include <uriparser/Uri.h>  # include "UriNormalizeBase.h"  # include "UriCommon.h" +# include "UriMemory.h"  #endif +#include <assert.h> + + +  static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, -		unsigned int * outMask); +		unsigned int * outMask, UriMemoryManager * memory);  static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, -		unsigned int maskTest, URI_TYPE(TextRange) * range); +		unsigned int maskTest, URI_TYPE(TextRange) * range, +		UriMemoryManager * memory);  static UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri, -		unsigned int * doneMask); +		unsigned int * doneMask, UriMemoryManager * memory);  static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,  		const URI_CHAR ** afterLast);  static UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first, -		const URI_CHAR ** afterLast); +		const URI_CHAR ** afterLast, UriMemoryManager * memory);  static void URI_FUNC(FixPercentEncodingEngine)(  		const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,  		const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast); @@ -99,23 +105,23 @@ static UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,  static void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,  		const URI_CHAR * afterLast);  static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, -		const URI_CHAR ** afterLast); +		const URI_CHAR ** afterLast, UriMemoryManager * memory);  static void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, -		unsigned int revertMask); +		unsigned int revertMask, UriMemoryManager * memory);  static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, -		unsigned int revertMask) { +		unsigned int revertMask, UriMemoryManager * memory) {  	if (revertMask & URI_NORMALIZE_SCHEME) { -		free((URI_CHAR *)uri->scheme.first); +		memory->free(memory, (URI_CHAR *)uri->scheme.first);  		uri->scheme.first = NULL;  		uri->scheme.afterLast = NULL;  	}  	if (revertMask & URI_NORMALIZE_USER_INFO) { -		free((URI_CHAR *)uri->userInfo.first); +		memory->free(memory, (URI_CHAR *)uri->userInfo.first);  		uri->userInfo.first = NULL;  		uri->userInfo.afterLast = NULL;  	} @@ -123,7 +129,7 @@ static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,  	if (revertMask & URI_NORMALIZE_HOST) {  		if (uri->hostData.ipFuture.first != NULL) {  			/* IPvFuture */ -			free((URI_CHAR *)uri->hostData.ipFuture.first); +			memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first);  			uri->hostData.ipFuture.first = NULL;  			uri->hostData.ipFuture.afterLast = NULL;  			uri->hostText.first = NULL; @@ -132,7 +138,7 @@ static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,  				&& (uri->hostData.ip4 == NULL)  				&& (uri->hostData.ip6 == NULL)) {  			/* Regname */ -			free((URI_CHAR *)uri->hostText.first); +			memory->free(memory, (URI_CHAR *)uri->hostText.first);  			uri->hostText.first = NULL;  			uri->hostText.afterLast = NULL;  		} @@ -145,9 +151,9 @@ static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,  		while (walker != NULL) {  			URI_TYPE(PathSegment) * const next = walker->next;  			if (walker->text.afterLast > walker->text.first) { -				free((URI_CHAR *)walker->text.first); +				memory->free(memory, (URI_CHAR *)walker->text.first);  			} -			free(walker); +			memory->free(memory, walker);  			walker = next;  		}  		uri->pathHead = NULL; @@ -155,13 +161,13 @@ static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,  	}  	if (revertMask & URI_NORMALIZE_QUERY) { -		free((URI_CHAR *)uri->query.first); +		memory->free(memory, (URI_CHAR *)uri->query.first);  		uri->query.first = NULL;  		uri->query.afterLast = NULL;  	}  	if (revertMask & URI_NORMALIZE_FRAGMENT) { -		free((URI_CHAR *)uri->fragment.first); +		memory->free(memory, (URI_CHAR *)uri->fragment.first);  		uri->fragment.first = NULL;  		uri->fragment.afterLast = NULL;  	} @@ -230,7 +236,7 @@ static URI_INLINE void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,  static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, -		const URI_CHAR ** afterLast) { +		const URI_CHAR ** afterLast, UriMemoryManager * memory) {  	int lenInChars;  	const int lowerUpperDiff = (_UT('a') - _UT('A'));  	URI_CHAR * buffer; @@ -248,7 +254,7 @@ static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,  		return URI_FALSE;  	} -	buffer = malloc(lenInChars * sizeof(URI_CHAR)); +	buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));  	if (buffer == NULL) {  		return URI_FALSE;  	} @@ -330,7 +336,7 @@ static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * firs  static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first, -		const URI_CHAR ** afterLast) { +		const URI_CHAR ** afterLast, UriMemoryManager * memory) {  	int lenInChars;  	URI_CHAR * buffer; @@ -349,7 +355,7 @@ static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** f  	}  	/* New buffer */ -	buffer = malloc(lenInChars * sizeof(URI_CHAR)); +	buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));  	if (buffer == NULL) {  		return URI_FALSE;  	} @@ -363,14 +369,15 @@ static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** f  static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, -		unsigned int maskTest, URI_TYPE(TextRange) * range) { +		unsigned int maskTest, URI_TYPE(TextRange) * range, +		UriMemoryManager * memory) {  	if (((*doneMask & maskTest) == 0)  			&& (range->first != NULL)  			&& (range->afterLast != NULL)  			&& (range->afterLast > range->first)) {  		const int lenInChars = (int)(range->afterLast - range->first);  		const int lenInBytes = lenInChars * sizeof(URI_CHAR); -		URI_CHAR * dup = malloc(lenInBytes); +		URI_CHAR * dup = memory->malloc(memory, lenInBytes);  		if (dup == NULL) {  			return URI_FALSE; /* Raises malloc error */  		} @@ -385,16 +392,16 @@ static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,  static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri, -		unsigned int * doneMask) { +		unsigned int * doneMask, UriMemoryManager * memory) {  	URI_TYPE(PathSegment) * walker = uri->pathHead;  	if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME, -				&(uri->scheme)) +				&(uri->scheme), memory)  			|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO, -				&(uri->userInfo)) +				&(uri->userInfo), memory)  			|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY, -				&(uri->query)) +				&(uri->query), memory)  			|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT, -				&(uri->fragment))) { +				&(uri->fragment), memory)) {  		return URI_FALSE; /* Raises malloc error */  	} @@ -405,7 +412,7 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  			if (uri->hostData.ipFuture.first != NULL) {  				/* IPvFuture */  				if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, -						&(uri->hostData.ipFuture))) { +						&(uri->hostData.ipFuture), memory)) {  					return URI_FALSE; /* Raises malloc error */  				}  				uri->hostText.first = uri->hostData.ipFuture.first; @@ -413,7 +420,7 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  			} else if (uri->hostText.first != NULL) {  				/* Regname */  				if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, -						&(uri->hostText))) { +						&(uri->hostText), memory)) {  					return URI_FALSE; /* Raises malloc error */  				}  			} @@ -423,7 +430,7 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  	/* Path */  	if ((*doneMask & URI_NORMALIZE_PATH) == 0) {  		while (walker != NULL) { -			if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text))) { +			if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text), memory)) {  				/* Free allocations done so far and kill path */  				/* Kill path to one before walker (if any) */ @@ -433,16 +440,16 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  					if ((ranger->text.first != NULL)  							&& (ranger->text.afterLast != NULL)  							&& (ranger->text.afterLast > ranger->text.first)) { -						free((URI_CHAR *)ranger->text.first); +						memory->free(memory, (URI_CHAR *)ranger->text.first);  					} -					free(ranger); +					memory->free(memory, ranger);  					ranger = next;  				}  				/* Kill path from walker */  				while (walker != NULL) {  					URI_TYPE(PathSegment) * const next = walker->next; -					free(walker); +					memory->free(memory, walker);  					walker = next;  				} @@ -458,7 +465,7 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  	/* Port text, must come last so we don't have to undo that one if it fails. *  	 * Otherwise we would need and extra enum flag for it although the port      *  	 * cannot go unnormalized...                                                */ -	if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->portText))) { +	if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->portText), memory)) {  		return URI_FALSE; /* Raises malloc error */  	} @@ -468,23 +475,50 @@ static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,  unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) { -	unsigned int res; +	unsigned int outMask = URI_NORMALIZED;  /* for NULL uri */ +	URI_FUNC(NormalizeSyntaxMaskRequiredEx)(uri, &outMask); +	return outMask; +} + + + +int URI_FUNC(NormalizeSyntaxMaskRequiredEx)(const URI_TYPE(Uri) * uri, +		unsigned int * outMask) { +	UriMemoryManager * const memory = NULL;  /* no use of memory manager */ +  #if defined(__GNUC__) && ((__GNUC__ > 4) \ -        || ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) -    /* Slower code that fixes a warning, not sure if this is a smart idea */ +		|| ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) +	/* Slower code that fixes a warning, not sure if this is a smart idea */  	URI_TYPE(Uri) writeableClone; +#endif + +	if ((uri == NULL) || (outMask == NULL)) { +		return URI_ERROR_NULL; +	} + +#if defined(__GNUC__) && ((__GNUC__ > 4) \ +		|| ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2))) +	/* Slower code that fixes a warning, not sure if this is a smart idea */  	memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri))); -	URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, &res); +	URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, outMask, memory);  #else -	URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, &res); +	URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, outMask, memory);  #endif -	return res; +	return URI_SUCCESS;  }  int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) { -	return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL); +	return URI_FUNC(NormalizeSyntaxExMm)(uri, mask, NULL); +} + + + +int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, unsigned int mask, +		UriMemoryManager * memory) { +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ +	return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL, memory);  } @@ -495,8 +529,16 @@ int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) { -static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, unsigned int * outMask) { +static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, +		unsigned int inMask, unsigned int * outMask, +		UriMemoryManager * memory) {  	unsigned int doneMask = URI_NORMALIZED; + +	/* Not just doing inspection? -> memory manager required! */ +	if (outMask == NULL) { +		assert(memory != NULL); +	} +  	if (uri == NULL) {  		if (outMask != NULL) {  			*outMask = URI_NORMALIZED; @@ -539,8 +581,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  			if (uri->owner) {  				URI_FUNC(LowercaseInplace)(uri->scheme.first, uri->scheme.afterLast);  			} else { -				if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast))) { -					URI_FUNC(PreventLeakage)(uri, doneMask); +				if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast), memory)) { +					URI_FUNC(PreventLeakage)(uri, doneMask, memory);  					return URI_ERROR_MALLOC;  				}  				doneMask |= URI_NORMALIZE_SCHEME; @@ -556,8 +598,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  							uri->hostData.ipFuture.afterLast);  				} else {  					if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first), -							&(uri->hostData.ipFuture.afterLast))) { -						URI_FUNC(PreventLeakage)(uri, doneMask); +							&(uri->hostData.ipFuture.afterLast), memory)) { +						URI_FUNC(PreventLeakage)(uri, doneMask, memory);  						return URI_ERROR_MALLOC;  					}  					doneMask |= URI_NORMALIZE_HOST; @@ -574,8 +616,9 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  				} else {  					if (!URI_FUNC(FixPercentEncodingMalloc)(  							&(uri->hostText.first), -							&(uri->hostText.afterLast))) { -						URI_FUNC(PreventLeakage)(uri, doneMask); +							&(uri->hostText.afterLast), +							memory)) { +						URI_FUNC(PreventLeakage)(uri, doneMask, memory);  						return URI_ERROR_MALLOC;  					}  					doneMask |= URI_NORMALIZE_HOST; @@ -600,8 +643,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  				URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, &(uri->userInfo.afterLast));  			} else {  				if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first), -						&(uri->userInfo.afterLast))) { -					URI_FUNC(PreventLeakage)(uri, doneMask); +						&(uri->userInfo.afterLast), memory)) { +					URI_FUNC(PreventLeakage)(uri, doneMask, memory);  					return URI_ERROR_MALLOC;  				}  				doneMask |= URI_NORMALIZE_USER_INFO; @@ -648,8 +691,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  		} else {  			while (walker != NULL) {  				if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first), -						&(walker->text.afterLast))) { -					URI_FUNC(PreventLeakage)(uri, doneMask); +						&(walker->text.afterLast), memory)) { +					URI_FUNC(PreventLeakage)(uri, doneMask, memory);  					return URI_ERROR_MALLOC;  				}  				walker = walker->next; @@ -660,12 +703,12 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  		/* 6.2.2.3 Path Segment Normalization */  		if (!URI_FUNC(RemoveDotSegmentsEx)(uri, relative,  				(uri->owner == URI_TRUE) -				|| ((doneMask & URI_NORMALIZE_PATH) != 0) -				)) { -			URI_FUNC(PreventLeakage)(uri, doneMask); +				|| ((doneMask & URI_NORMALIZE_PATH) != 0), +				memory)) { +			URI_FUNC(PreventLeakage)(uri, doneMask, memory);  			return URI_ERROR_MALLOC;  		} -		URI_FUNC(FixEmptyTrailSegment)(uri); +		URI_FUNC(FixEmptyTrailSegment)(uri, memory);  	}  	/* Query, fragment */ @@ -688,8 +731,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  				URI_FUNC(FixPercentEncodingInplace)(uri->query.first, &(uri->query.afterLast));  			} else {  				if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first), -						&(uri->query.afterLast))) { -					URI_FUNC(PreventLeakage)(uri, doneMask); +						&(uri->query.afterLast), memory)) { +					URI_FUNC(PreventLeakage)(uri, doneMask, memory);  					return URI_ERROR_MALLOC;  				}  				doneMask |= URI_NORMALIZE_QUERY; @@ -702,8 +745,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  				URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, &(uri->fragment.afterLast));  			} else {  				if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first), -						&(uri->fragment.afterLast))) { -					URI_FUNC(PreventLeakage)(uri, doneMask); +						&(uri->fragment.afterLast), memory)) { +					URI_FUNC(PreventLeakage)(uri, doneMask, memory);  					return URI_ERROR_MALLOC;  				}  				doneMask |= URI_NORMALIZE_FRAGMENT; @@ -713,8 +756,8 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsig  	/* Dup all not duped yet */  	if ((outMask == NULL) && !uri->owner) { -		if (!URI_FUNC(MakeOwner)(uri, &doneMask)) { -			URI_FUNC(PreventLeakage)(uri, doneMask); +		if (!URI_FUNC(MakeOwner)(uri, &doneMask, memory)) { +			URI_FUNC(PreventLeakage)(uri, doneMask, memory);  			return URI_ERROR_MALLOC;  		}  		uri->owner = URI_TRUE; diff --git a/src/UriParse.c b/src/UriParse.c index e087753..f4bdda9 100644 --- a/src/UriParse.c +++ b/src/UriParse.c @@ -71,6 +71,7 @@  # include <uriparser/Uri.h>  # include <uriparser/UriIp4.h>  # include "UriCommon.h" +# include "UriMemory.h"  # include "UriParseBase.h"  #endif @@ -155,64 +156,70 @@ -static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); +static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory);  static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);  static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); +static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory);  static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); - -static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first); -static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first); -static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first); -static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first); +static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); +static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); + +static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory); +static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, UriMemoryManager * memory);  static void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state);  static void URI_FUNC(ResetParserStateExceptUri)(URI_TYPE(ParserState) * state); -static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); +static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory); -static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos); -static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state); +static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos, UriMemoryManager * memory); +static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, UriMemoryManager * memory); + +static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory);  static URI_INLINE void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, -		const URI_CHAR * errorPos) { -	URI_FUNC(FreeUriMembers)(state->uri); +		const URI_CHAR * errorPos, UriMemoryManager * memory) { +	URI_FUNC(FreeUriMembersMm)(state->uri, memory);  	state->errorPos = errorPos;  	state->errorCode = URI_ERROR_SYNTAX;  } -static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state) { -	URI_FUNC(FreeUriMembers)(state->uri); +static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state, UriMemoryManager * memory) { +	URI_FUNC(FreeUriMembersMm)(state->uri, memory);  	state->errorPos = NULL;  	state->errorCode = URI_ERROR_MALLOC;  } @@ -224,7 +231,9 @@ static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state) {   * [authority]->[ownHostUserInfoNz]   * [authority]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		/* "" regname host */  		state->uri->hostText.first = URI_FUNC(SafeToPointTo); @@ -236,7 +245,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState  	case _UT('['):  		{  			const URI_CHAR * const afterIpLit2 -					= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast); +					= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory);  			if (afterIpLit2 == NULL) {  				return NULL;  			} @@ -265,7 +274,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState  	case URI_SET_DIGIT:  	case URI_SET_ALPHA:  		state->uri->userInfo.first = first; /* USERINFO BEGIN */ -		return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast); +		return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory);  	default:  		/* "" regname host */ @@ -330,7 +339,9 @@ static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, co   * [hierPart]-></>[partHelperTwo]   * [hierPart]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -356,10 +367,10 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState)  	case _UT('='):  	case URI_SET_DIGIT:  	case URI_SET_ALPHA: -		return URI_FUNC(ParsePathRootless)(state, first, afterLast); +		return URI_FUNC(ParsePathRootless)(state, first, afterLast, memory);  	case _UT('/'): -		return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast); +		return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory);  	default:  		return first; @@ -373,9 +384,11 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState)   * [ipFutLoop]->[unreserved][ipFutStopGo]   * [ipFutLoop]-><:>[ipFutStopGo]   */ -static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -398,10 +411,10 @@ static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state,  	case _UT('='):  	case URI_SET_DIGIT:  	case URI_SET_ALPHA: -		return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast); +		return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast, memory);  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } @@ -412,7 +425,10 @@ static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state,   * [ipFutStopGo]->[ipFutLoop]   * [ipFutStopGo]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -436,7 +452,7 @@ static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state  	case _UT('='):  	case URI_SET_DIGIT:  	case URI_SET_ALPHA: -		return URI_FUNC(ParseIpFutLoop)(state, first, afterLast); +		return URI_FUNC(ParseIpFutLoop)(state, first, afterLast, memory);  	default:  		return first; @@ -448,9 +464,11 @@ static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state  /*   * [ipFuture]-><v>[HEXDIG][hexZero]<.>[ipFutLoop]   */ -static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -462,7 +480,7 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, c  	case _UT('v'):  	*/  		if (first + 1 >= afterLast) { -			URI_FUNC(StopSyntax)(state, first + 1); +			URI_FUNC(StopSyntax)(state, first + 1, memory);  			return NULL;  		} @@ -477,12 +495,12 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, c  				}  				if ((afterHexZero >= afterLast)  						|| (*afterHexZero != _UT('.'))) { -					URI_FUNC(StopSyntax)(state, afterHexZero); +					URI_FUNC(StopSyntax)(state, afterHexZero, memory);  					return NULL;  				}  				state->uri->hostText.first = first; /* HOST BEGIN */  				state->uri->hostData.ipFuture.first = first; /* IPFUTURE BEGIN */ -				afterIpFutLoop = URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast); +				afterIpFutLoop = URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast, memory);  				if (afterIpFutLoop == NULL) {  					return NULL;  				} @@ -492,13 +510,13 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, c  			}  		default: -			URI_FUNC(StopSyntax)(state, first + 1); +			URI_FUNC(StopSyntax)(state, first + 1, memory);  			return NULL;  		}  	/*  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  	*/ @@ -510,9 +528,11 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, c   * [ipLit2]->[ipFuture]<]>   * [ipLit2]->[IPv6address2]   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -520,13 +540,13 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) *  	case _UT('v'):  		{  			const URI_CHAR * const afterIpFuture -					= URI_FUNC(ParseIpFuture)(state, first, afterLast); +					= URI_FUNC(ParseIpFuture)(state, first, afterLast, memory);  			if (afterIpFuture == NULL) {  				return NULL;  			}  			if ((afterIpFuture >= afterLast)  					|| (*afterIpFuture != _UT(']'))) { -				URI_FUNC(StopSyntax)(state, first); +				URI_FUNC(StopSyntax)(state, first, memory);  				return NULL;  			}  			return afterIpFuture + 1; @@ -535,15 +555,15 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) *  	case _UT(':'):  	case _UT(']'):  	case URI_SET_HEXDIG: -		state->uri->hostData.ip6 = malloc(1 * sizeof(UriIp6)); /* Freed when stopping on parse error */ +		state->uri->hostData.ip6 = memory->malloc(memory, 1 * sizeof(UriIp6)); /* Freed when stopping on parse error */  		if (state->uri->hostData.ip6 == NULL) { -			URI_FUNC(StopMalloc)(state); +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		} -		return URI_FUNC(ParseIPv6address2)(state, first, afterLast); +		return URI_FUNC(ParseIPv6address2)(state, first, afterLast, memory);  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } @@ -553,7 +573,10 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) *  /*   * [IPv6address2]->..<]>   */ -static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseIPv6address2)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	int zipperEver = 0;  	int quadsDone = 0;  	int digitCount = 0; @@ -566,7 +589,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  	for (;;) {  		if (first >= afterLast) { -			URI_FUNC(StopSyntax)(state, first); +			URI_FUNC(StopSyntax)(state, first, memory);  			return NULL;  		} @@ -577,7 +600,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  				switch (*first) {  				case URI_SET_DIGIT:  					if (digitCount == 4) { -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					}  					digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9')); @@ -588,17 +611,17 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  							|| (digitCount == 0)  							|| (digitCount == 4)) {  						/* Invalid digit or octet count */ -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					} else if ((digitCount > 1)  							&& (digitHistory[0] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount); +						URI_FUNC(StopSyntax)(state, first - digitCount, memory);  						return NULL;  					} else if ((digitCount > 2)  							&& (digitHistory[1] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount + 1); +						URI_FUNC(StopSyntax)(state, first - digitCount + 1, memory);  						return NULL;  					} else if ((digitCount == 3)  							&& (100 * digitHistory[0] @@ -606,11 +629,11 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  								+ digitHistory[2] > 255)) {  						/* Octet value too large */  						if (digitHistory[0] > 2) { -							URI_FUNC(StopSyntax)(state, first - 3); +							URI_FUNC(StopSyntax)(state, first - 3, memory);  						} else if (digitHistory[1] > 5) { -							URI_FUNC(StopSyntax)(state, first - 2); +							URI_FUNC(StopSyntax)(state, first - 2, memory);  						} else { -							URI_FUNC(StopSyntax)(state, first - 1); +							URI_FUNC(StopSyntax)(state, first - 1, memory);  						}  						return NULL;  					} @@ -626,17 +649,17 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  							|| (digitCount == 0)  							|| (digitCount == 4)) {  						/* Invalid digit or octet count */ -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					} else if ((digitCount > 1)  							&& (digitHistory[0] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount); +						URI_FUNC(StopSyntax)(state, first - digitCount, memory);  						return NULL;  					} else if ((digitCount > 2)  							&& (digitHistory[1] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount + 1); +						URI_FUNC(StopSyntax)(state, first - digitCount + 1, memory);  						return NULL;  					} else if ((digitCount == 3)  							&& (100 * digitHistory[0] @@ -644,11 +667,11 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  								+ digitHistory[2] > 255)) {  						/* Octet value too large */  						if (digitHistory[0] > 2) { -							URI_FUNC(StopSyntax)(state, first - 3); +							URI_FUNC(StopSyntax)(state, first - 3, memory);  						} else if (digitHistory[1] > 5) { -							URI_FUNC(StopSyntax)(state, first - 2); +							URI_FUNC(StopSyntax)(state, first - 2, memory);  						} else { -							URI_FUNC(StopSyntax)(state, first - 1); +							URI_FUNC(StopSyntax)(state, first - 1, memory);  						}  						return NULL;  					} @@ -665,7 +688,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  					return first + 1;  				default: -					URI_FUNC(StopSyntax)(state, first); +					URI_FUNC(StopSyntax)(state, first, memory);  					return NULL;  				}  				first++; @@ -679,7 +702,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  				case URI_SET_HEX_LETTER_LOWER:  					letterAmong = 1;  					if (digitCount == 4) { -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					}  					digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f')); @@ -689,7 +712,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  				case URI_SET_HEX_LETTER_UPPER:  					letterAmong = 1;  					if (digitCount == 4) { -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					}  					digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F')); @@ -698,7 +721,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  				case URI_SET_DIGIT:  					if (digitCount == 4) { -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					}  					digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9')); @@ -723,13 +746,13 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  						/* Too many quads? */  						if (quadsDone >= 8 - zipperEver) { -							URI_FUNC(StopSyntax)(state, first); +							URI_FUNC(StopSyntax)(state, first, memory);  							return NULL;  						}  						/* "::"? */  						if (first + 1 >= afterLast) { -							URI_FUNC(StopSyntax)(state, first + 1); +							URI_FUNC(StopSyntax)(state, first + 1, memory);  							return NULL;  						}  						if (first[1] == _UT(':')) { @@ -737,7 +760,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  							first++;  							if (zipperEver) { -								URI_FUNC(StopSyntax)(state, first); +								URI_FUNC(StopSyntax)(state, first, memory);  								return NULL; /* "::.+::" */  							} @@ -747,11 +770,11 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  							/* ":::+"? */  							if (first + 1 >= afterLast) { -								URI_FUNC(StopSyntax)(state, first + 1); +								URI_FUNC(StopSyntax)(state, first + 1, memory);  								return NULL; /* No ']' yet */  							}  							if (first[1] == _UT(':')) { -								URI_FUNC(StopSyntax)(state, first + 1); +								URI_FUNC(StopSyntax)(state, first + 1, memory);  								return NULL; /* ":::+ "*/  							}  						} @@ -769,17 +792,17 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  							|| (digitCount == 0)  							|| (digitCount == 4)) {  						/* Invalid octet before */ -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					} else if ((digitCount > 1)  							&& (digitHistory[0] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount); +						URI_FUNC(StopSyntax)(state, first - digitCount, memory);  						return NULL;  					} else if ((digitCount > 2)  							&& (digitHistory[1] == 0)) {  						/* Leading zero */ -						URI_FUNC(StopSyntax)(state, first - digitCount + 1); +						URI_FUNC(StopSyntax)(state, first - digitCount + 1, memory);  						return NULL;  					} else if ((digitCount == 3)  							&& (100 * digitHistory[0] @@ -787,11 +810,11 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  								+ digitHistory[2] > 255)) {  						/* Octet value too large */  						if (digitHistory[0] > 2) { -							URI_FUNC(StopSyntax)(state, first - 3); +							URI_FUNC(StopSyntax)(state, first - 3, memory);  						} else if (digitHistory[1] > 5) { -							URI_FUNC(StopSyntax)(state, first - 2); +							URI_FUNC(StopSyntax)(state, first - 2, memory);  						} else { -							URI_FUNC(StopSyntax)(state, first - 1); +							URI_FUNC(StopSyntax)(state, first - 1, memory);  						}  						return NULL;  					} @@ -808,7 +831,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  				case _UT(']'):  					/* Too little quads? */  					if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) { -						URI_FUNC(StopSyntax)(state, first); +						URI_FUNC(StopSyntax)(state, first, memory);  						return NULL;  					} @@ -833,13 +856,13 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat  					return first + 1; /* Fine */  				default: -					URI_FUNC(StopSyntax)(state, first); +					URI_FUNC(StopSyntax)(state, first, memory);  					return NULL;  				}  				first++;  				if (first >= afterLast) { -					URI_FUNC(StopSyntax)(state, first); +					URI_FUNC(StopSyntax)(state, first, memory);  					return NULL; /* No ']' yet */  				}  			} while (walking); @@ -857,10 +880,12 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat   * [mustBeSegmentNzNc]-></>[segment][zeroMoreSlashSegs][uriTail]   * [mustBeSegmentNzNc]-><@>[mustBeSegmentNzNc]   */ -static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */ -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		state->uri->scheme.first = NULL; /* Not a scheme, reset */ @@ -871,11 +896,11 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) *  	case _UT('%'):  		{  			const URI_CHAR * const afterPctEncoded -					= URI_FUNC(ParsePctEncoded)(state, first, afterLast); +					= URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  			if (afterPctEncoded == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast); +			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory);  		}  	case _UT('@'): @@ -896,40 +921,40 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) *  	case _UT('~'):  	case URI_SET_DIGIT:  	case URI_SET_ALPHA: -		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast); +		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory);  	case _UT('/'):  		{  			const URI_CHAR * afterZeroMoreSlashSegs;  			const URI_CHAR * afterSegment; -			if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			}  			state->uri->scheme.first = NULL; /* Not a scheme, reset */ -			afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast); +			afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory);  			if (afterSegment == NULL) {  				return NULL;  			} -			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			}  			afterZeroMoreSlashSegs -					= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast); +					= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory);  			if (afterZeroMoreSlashSegs == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast); +			return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory);  		}  	default: -		if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */ -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		state->uri->scheme.first = NULL; /* Not a scheme, reset */ -		return URI_FUNC(ParseUriTail)(state, first, afterLast); +		return URI_FUNC(ParseUriTail)(state, first, afterLast, memory);  	}  } @@ -939,7 +964,9 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) *   * [ownHost]-><[>[ipLit2][authorityTwo]   * [ownHost]->[ownHost2] // can take <NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		state->uri->hostText.afterLast = afterLast; /* HOST END */  		return afterLast; @@ -949,7 +976,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState)  	case _UT('['):  		{  			const URI_CHAR * const afterIpLit2 -					= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast); +					= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast, memory);  			if (afterIpLit2 == NULL) {  				return NULL;  			} @@ -958,24 +985,26 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState)  		}  	default: -		return URI_FUNC(ParseOwnHost2)(state, first, afterLast); +		return URI_FUNC(ParseOwnHost2)(state, first, afterLast, memory);  	}  } -static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) { +static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		UriMemoryManager * memory) {  	state->uri->hostText.afterLast = first; /* HOST END */  	/* Valid IPv4 or just a regname? */ -	state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ +	state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */  	if (state->uri->hostData.ip4 == NULL) {  		return URI_FALSE; /* Raises malloc error */  	}  	if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,  			state->uri->hostText.first, state->uri->hostText.afterLast)) {  		/* Not IPv4 */ -		free(state->uri->hostData.ip4); +		memory->free(memory, state->uri->hostData.ip4);  		state->uri->hostData.ip4 = NULL;  	}  	return URI_TRUE; /* Success */ @@ -987,10 +1016,12 @@ static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state   * [ownHost2]->[authorityTwo] // can take <NULL>   * [ownHost2]->[pctSubUnres][ownHost2]   */ -static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseOwnHost2)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		if (!URI_FUNC(OnExitOwnHost2)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return afterLast; @@ -1017,16 +1048,16 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, c  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterPctSubUnres -					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast); +					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory);  			if (afterPctSubUnres == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast); +			return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast, memory);  		}  	default: -		if (!URI_FUNC(OnExitOwnHost2)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast); @@ -1035,20 +1066,22 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, c -static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first) { +static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		UriMemoryManager * memory) {  	state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */  	state->uri->userInfo.first = NULL; /* Not a userInfo, reset */  	state->uri->hostText.afterLast = first; /* HOST END */  	/* Valid IPv4 or just a regname? */ -	state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ +	state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */  	if (state->uri->hostData.ip4 == NULL) {  		return URI_FALSE; /* Raises malloc error */  	}  	if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,  			state->uri->hostText.first, state->uri->hostText.afterLast)) {  		/* Not IPv4 */ -		free(state->uri->hostData.ip4); +		memory->free(memory, state->uri->hostData.ip4);  		state->uri->hostData.ip4 = NULL;  	}  	return URI_TRUE; /* Success */ @@ -1060,10 +1093,12 @@ static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState)   * [ownHostUserInfo]->[ownHostUserInfoNz]   * [ownHostUserInfo]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return afterLast; @@ -1090,11 +1125,11 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(Parse  	case _UT('='):  	case URI_SET_DIGIT:  	case URI_SET_ALPHA: -		return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast); +		return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory);  	default: -		if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return first; @@ -1108,9 +1143,11 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(Parse   * [ownHostUserInfoNz]-><:>[ownPortUserInfo]   * [ownHostUserInfoNz]-><@>[ownHost]   */ -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -1135,45 +1172,47 @@ static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) *  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterPctSubUnres -					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast); +					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory);  			if (afterPctSubUnres == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast); +			return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast, memory);  		}  	case _UT(':'):  		state->uri->hostText.afterLast = first; /* HOST END */  		state->uri->portText.first = first + 1; /* PORT BEGIN */ -		return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory);  	case _UT('@'):  		state->uri->userInfo.afterLast = first; /* USERINFO END */  		state->uri->hostText.first = first + 1; /* HOST BEGIN */ -		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory);  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } -static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first) { +static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		UriMemoryManager * memory) {  	state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */  	state->uri->userInfo.first = NULL; /* Not a userInfo, reset */  	state->uri->portText.afterLast = first; /* PORT END */  	/* Valid IPv4 or just a regname? */ -	state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */ +	state->uri->hostData.ip4 = memory->malloc(memory, 1 * sizeof(UriIp4)); /* Freed when stopping on parse error */  	if (state->uri->hostData.ip4 == NULL) {  		return URI_FALSE; /* Raises malloc error */  	}  	if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,  			state->uri->hostText.first, state->uri->hostText.afterLast)) {  		/* Not IPv4 */ -		free(state->uri->hostData.ip4); +		memory->free(memory, state->uri->hostData.ip4);  		state->uri->hostData.ip4 = NULL;  	}  	return URI_TRUE; /* Success */ @@ -1194,10 +1233,12 @@ static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState)   * [ownPortUserInfo]-><@>[ownHost]   * [ownPortUserInfo]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return afterLast; @@ -1227,20 +1268,20 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s  	case URI_SET_ALPHA:  		state->uri->hostText.afterLast = NULL; /* Not a host, reset */  		state->uri->portText.first = NULL; /* Not a port, reset */ -		return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory);  	case URI_SET_DIGIT: -		return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory);  	case _UT('%'):  		state->uri->portText.first = NULL; /* Not a port, reset */  		{  			const URI_CHAR * const afterPct -					= URI_FUNC(ParsePctEncoded)(state, first, afterLast); +					= URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  			if (afterPct == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseOwnUserInfo)(state, afterPct, afterLast); +			return URI_FUNC(ParseOwnUserInfo)(state, afterPct, afterLast, memory);  		}  	case _UT('@'): @@ -1248,11 +1289,11 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s  		state->uri->portText.first = NULL; /* Not a port, reset */  		state->uri->userInfo.afterLast = first; /* USERINFO END */  		state->uri->hostText.first = first + 1; /* HOST BEGIN */ -		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory);  	default: -		if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return first; @@ -1266,9 +1307,11 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s   * [ownUserInfo]-><:>[ownUserInfo]   * [ownUserInfo]-><@>[ownHost]   */ -static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -1293,24 +1336,24 @@ static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterPctSubUnres -					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast); +					= URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory);  			if (afterPctSubUnres == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast); +			return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast, memory);  		}  	case _UT(':'): -		return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory);  	case _UT('@'):  		/* SURE */  		state->uri->userInfo.afterLast = first; /* USERINFO END */  		state->uri->hostText.first = first + 1; /* HOST BEGIN */ -		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast); +		return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory);  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } @@ -1327,7 +1370,9 @@ static URI_INLINE void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * sta   * [partHelperTwo]->[pathAbsNoLeadSlash] // can take <NULL>   * [partHelperTwo]-></>[authority][pathAbsEmpty]   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		URI_FUNC(OnExitPartHelperTwo)(state);  		return afterLast; @@ -1337,21 +1382,21 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserS  	case _UT('/'):  		{  			const URI_CHAR * const afterAuthority -					= URI_FUNC(ParseAuthority)(state, first + 1, afterLast); +					= URI_FUNC(ParseAuthority)(state, first + 1, afterLast, memory);  			const URI_CHAR * afterPathAbsEmpty;  			if (afterAuthority == NULL) {  				return NULL;  			} -			afterPathAbsEmpty = URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast); +			afterPathAbsEmpty = URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast, memory); -			URI_FUNC(FixEmptyTrailSegment)(state->uri); +			URI_FUNC(FixEmptyTrailSegment)(state->uri, memory);  			return afterPathAbsEmpty;  		}  	default:  		URI_FUNC(OnExitPartHelperTwo)(state); -		return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast); +		return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast, memory);  	}  } @@ -1361,7 +1406,9 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserS   * [pathAbsEmpty]-></>[segment][pathAbsEmpty]   * [pathAbsEmpty]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1370,15 +1417,15 @@ static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * stat  	case _UT('/'):  		{  			const URI_CHAR * const afterSegment -					= URI_FUNC(ParseSegment)(state, first + 1, afterLast); +					= URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory);  			if (afterSegment == NULL) {  				return NULL;  			} -			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			} -			return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast); +			return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast, memory);  		}  	default: @@ -1392,7 +1439,9 @@ static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * stat   * [pathAbsNoLeadSlash]->[segmentNz][zeroMoreSlashSegs]   * [pathAbsNoLeadSlash]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1420,15 +1469,15 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(Pa  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterSegmentNz -					= URI_FUNC(ParseSegmentNz)(state, first, afterLast); +					= URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory);  			if (afterSegmentNz == NULL) {  				return NULL;  			} -			if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			} -			return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast); +			return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory);  		}  	default: @@ -1441,18 +1490,20 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(Pa  /*   * [pathRootless]->[segmentNz][zeroMoreSlashSegs]   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	const URI_CHAR * const afterSegmentNz -			= URI_FUNC(ParseSegmentNz)(state, first, afterLast); +			= URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory);  	if (afterSegmentNz == NULL) {  		return NULL;  	} else { -		if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */ -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz, memory)) { /* SEGMENT BOTH */ +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  	} -	return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast); +	return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast, memory);  } @@ -1464,15 +1515,17 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserSt   * [pchar]-><:>   * [pchar]-><@>   */ -static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  	switch (*first) {  	case _UT('%'): -		return URI_FUNC(ParsePctEncoded)(state, first, afterLast); +		return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  	case _UT(':'):  	case _UT('@'): @@ -1496,7 +1549,7 @@ static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, cons  		return first + 1;  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } @@ -1506,9 +1559,12 @@ static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, cons  /*   * [pctEncoded]-><%>[HEXDIG][HEXDIG]   */ -static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParsePctEncoded)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	} @@ -1520,14 +1576,14 @@ static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state,  	case _UT('%'):  	*/  		if (first + 1 >= afterLast) { -			URI_FUNC(StopSyntax)(state, first + 1); +			URI_FUNC(StopSyntax)(state, first + 1, memory);  			return NULL;  		}  		switch (first[1]) {  		case URI_SET_HEXDIG:  			if (first + 2 >= afterLast) { -				URI_FUNC(StopSyntax)(state, first + 2); +				URI_FUNC(StopSyntax)(state, first + 2, memory);  				return NULL;  			} @@ -1536,18 +1592,18 @@ static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state,  				return first + 3;  			default: -				URI_FUNC(StopSyntax)(state, first + 2); +				URI_FUNC(StopSyntax)(state, first + 2, memory);  				return NULL;  			}  		default: -			URI_FUNC(StopSyntax)(state, first + 1); +			URI_FUNC(StopSyntax)(state, first + 1, memory);  			return NULL;  		}  	/*  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  	*/ @@ -1560,15 +1616,18 @@ static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state,   * [pctSubUnres]->[subDelims]   * [pctSubUnres]->[unreserved]   */ -static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParsePctSubUnres)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) { -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  	switch (*first) {  	case _UT('%'): -		return URI_FUNC(ParsePctEncoded)(state, first, afterLast); +		return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  	case _UT('!'):  	case _UT('$'): @@ -1590,7 +1649,7 @@ static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state  		return first + 1;  	default: -		URI_FUNC(StopSyntax)(state, first); +		URI_FUNC(StopSyntax)(state, first, memory);  		return NULL;  	}  } @@ -1623,7 +1682,9 @@ static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const   * [queryFrag]-><?>[queryFrag]   * [queryFrag]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1651,16 +1712,16 @@ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state,  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterPchar -					= URI_FUNC(ParsePchar)(state, first, afterLast); +					= URI_FUNC(ParsePchar)(state, first, afterLast, memory);  			if (afterPchar == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast); +			return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast, memory);  		}  	case _UT('/'):  	case _UT('?'): -		return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast); +		return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory);  	default:  		return first; @@ -1673,7 +1734,9 @@ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state,   * [segment]->[pchar][segment]   * [segment]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1701,11 +1764,11 @@ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, co  	case URI_SET_ALPHA:  		{  			const URI_CHAR * const afterPchar -					= URI_FUNC(ParsePchar)(state, first, afterLast); +					= URI_FUNC(ParsePchar)(state, first, afterLast, memory);  			if (afterPchar == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseSegment)(state, afterPchar, afterLast); +			return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory);  		}  	default: @@ -1718,19 +1781,24 @@ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, co  /*   * [segmentNz]->[pchar][segment]   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseSegmentNz)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	const URI_CHAR * const afterPchar -			= URI_FUNC(ParsePchar)(state, first, afterLast); +			= URI_FUNC(ParsePchar)(state, first, afterLast, memory);  	if (afterPchar == NULL) {  		return NULL;  	} -	return URI_FUNC(ParseSegment)(state, afterPchar, afterLast); +	return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory);  } -static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) { -	if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */ +static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		UriMemoryManager * memory) { +	if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */  		return URI_FALSE; /* Raises malloc error*/  	}  	state->uri->scheme.first = NULL; /* Not a scheme, reset */ @@ -1763,10 +1831,12 @@ static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserSt   * [segmentNzNcOrScheme2]-><'>[mustBeSegmentNzNc]   * [segmentNzNcOrScheme2]-><->[segmentNzNcOrScheme2]   */ -static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) { -		if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		}  		return afterLast; @@ -1778,16 +1848,16 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState  	case _UT('-'):  	case URI_SET_ALPHA:  	case URI_SET_DIGIT: -		return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast); +		return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory);  	case _UT('%'):  		{  			const URI_CHAR * const afterPctEncoded -					= URI_FUNC(ParsePctEncoded)(state, first, afterLast); +					= URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  			if (afterPctEncoded == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast); +			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory);  		}  	case _UT('!'): @@ -1803,50 +1873,50 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState  	case _UT('~'):  	case _UT('='):  	case _UT('\''): -		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast); +		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory);  	case _UT('/'):  		{  			const URI_CHAR * afterZeroMoreSlashSegs;  			const URI_CHAR * const afterSegment -					= URI_FUNC(ParseSegment)(state, first + 1, afterLast); +					= URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory);  			if (afterSegment == NULL) {  				return NULL;  			} -			if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			}  			state->uri->scheme.first = NULL; /* Not a scheme, reset */ -			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			}  			afterZeroMoreSlashSegs -					= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast); +					= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory);  			if (afterZeroMoreSlashSegs == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast); +			return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast, memory);  		}  	case _UT(':'):  		{  			const URI_CHAR * const afterHierPart -					= URI_FUNC(ParseHierPart)(state, first + 1, afterLast); +					= URI_FUNC(ParseHierPart)(state, first + 1, afterLast, memory);  			state->uri->scheme.afterLast = first; /* SCHEME END */  			if (afterHierPart == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast); +			return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast, memory);  		}  	default: -		if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first)) { -			URI_FUNC(StopMalloc)(state); +		if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { +			URI_FUNC(StopMalloc)(state, memory);  			return NULL;  		} -		return URI_FUNC(ParseUriTail)(state, first, afterLast); +		return URI_FUNC(ParseUriTail)(state, first, afterLast, memory);  	}  } @@ -1865,7 +1935,9 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState   * [uriReference]-><~>[mustBeSegmentNzNc]   * [uriReference]-><->[mustBeSegmentNzNc]   */ -static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseUriReference)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1873,7 +1945,7 @@ static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * stat  	switch (*first) {  	case URI_SET_ALPHA:  		state->uri->scheme.first = first; /* SCHEME BEGIN */ -		return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast); +		return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory);  	case URI_SET_DIGIT:  	case _UT('!'): @@ -1893,31 +1965,31 @@ static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * stat  	case _UT('-'):  	case _UT('@'):  		state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ -		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast); +		return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory);  	case _UT('%'):  		{  			const URI_CHAR * const afterPctEncoded -					= URI_FUNC(ParsePctEncoded)(state, first, afterLast); +					= URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory);  			if (afterPctEncoded == NULL) {  				return NULL;  			}  			state->uri->scheme.first = first; /* SEGMENT BEGIN, ABUSE SCHEME POINTER */ -			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast); +			return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, memory);  		}  	case _UT('/'):  		{  			const URI_CHAR * const afterPartHelperTwo -					= URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast); +					= URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast, memory);  			if (afterPartHelperTwo == NULL) {  				return NULL;  			} -			return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast); +			return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast, memory);  		}  	default: -		return URI_FUNC(ParseUriTail)(state, first, afterLast); +		return URI_FUNC(ParseUriTail)(state, first, afterLast, memory);  	}  } @@ -1928,7 +2000,10 @@ static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * stat   * [uriTail]-><?>[queryFrag][uriTailTwo]   * [uriTail]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1936,7 +2011,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState)  	switch (*first) {  	case _UT('#'):  		{ -			const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast); +			const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory);  			if (afterQueryFrag == NULL) {  				return NULL;  			} @@ -1948,13 +2023,13 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState)  	case _UT('?'):  		{  			const URI_CHAR * const afterQueryFrag -					= URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast); +					= URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory);  			if (afterQueryFrag == NULL) {  				return NULL;  			}  			state->uri->query.first = first + 1; /* QUERY BEGIN */  			state->uri->query.afterLast = afterQueryFrag; /* QUERY END */ -			return URI_FUNC(ParseUriTailTwo)(state, afterQueryFrag, afterLast); +			return URI_FUNC(ParseUriTailTwo)(state, afterQueryFrag, afterLast, memory);  		}  	default: @@ -1968,7 +2043,10 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState)   * [uriTailTwo]-><#>[queryFrag]   * [uriTailTwo]-><NULL>   */ -static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)( +		URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -1976,7 +2054,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserStat  	switch (*first) {  	case _UT('#'):  		{ -			const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast); +			const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory);  			if (afterQueryFrag == NULL) {  				return NULL;  			} @@ -1996,7 +2074,9 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserStat   * [zeroMoreSlashSegs]-></>[segment][zeroMoreSlashSegs]   * [zeroMoreSlashSegs]-><NULL>   */ -static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) {  	if (first >= afterLast) {  		return afterLast;  	} @@ -2005,15 +2085,15 @@ static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) *  	case _UT('/'):  		{  			const URI_CHAR * const afterSegment -					= URI_FUNC(ParseSegment)(state, first + 1, afterLast); +					= URI_FUNC(ParseSegment)(state, first + 1, afterLast, memory);  			if (afterSegment == NULL) {  				return NULL;  			} -			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */ -				URI_FUNC(StopMalloc)(state); +			if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment, memory)) { /* SEGMENT BOTH */ +				URI_FUNC(StopMalloc)(state, memory);  				return NULL;  			} -			return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast); +			return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory);  		}  	default: @@ -2031,12 +2111,13 @@ static URI_INLINE void URI_FUNC(ResetParserStateExceptUri)(URI_TYPE(ParserState) -static URI_INLINE UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { -	URI_TYPE(PathSegment) * segment = malloc(1 * sizeof(URI_TYPE(PathSegment))); +static URI_INLINE UriBool URI_FUNC(PushPathSegment)( +		URI_TYPE(ParserState) * state, const URI_CHAR * first, +		const URI_CHAR * afterLast, UriMemoryManager * memory) { +	URI_TYPE(PathSegment) * segment = memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment)));  	if (segment == NULL) {  		return URI_FALSE; /* Raises malloc error */  	} -	memset(segment, 0, sizeof(URI_TYPE(PathSegment)));  	if (first == afterLast) {  		segment->text.first = URI_FUNC(SafeToPointTo);  		segment->text.afterLast = URI_FUNC(SafeToPointTo); @@ -2061,7 +2142,16 @@ static URI_INLINE UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * stat -int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) { +int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast) { +	return URI_FUNC(ParseUriExMm)(state, first, afterLast, NULL); +} + + + +static int URI_FUNC(ParseUriExMm)(URI_TYPE(ParserState) * state, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	const URI_CHAR * afterUriReference;  	URI_TYPE(Uri) * uri; @@ -2069,6 +2159,8 @@ int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first,  	if ((state == NULL) || (first == NULL) || (afterLast == NULL)) {  		return URI_ERROR_NULL;  	} +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ +  	uri = state->uri;  	/* Init parser */ @@ -2076,12 +2168,12 @@ int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first,  	URI_FUNC(ResetUri)(uri);  	/* Parse */ -	afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast); +	afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast, memory);  	if (afterUriReference == NULL) {  		return state->errorCode;  	}  	if (afterUriReference != afterLast) { -		URI_FUNC(StopSyntax)(state, afterUriReference); +		URI_FUNC(StopSyntax)(state, afterUriReference, memory);  		return state->errorCode;  	}  	return URI_SUCCESS; @@ -2098,16 +2190,70 @@ int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, const URI_CHAR * text) { +int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, const URI_CHAR * text, +		const URI_CHAR ** errorPos) { +	return URI_FUNC(ParseSingleUriEx)(uri, text, NULL, errorPos); +} + + + +int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		const URI_CHAR ** errorPos) { +    if ((afterLast == NULL) && (first != NULL)) { +		afterLast = first + URI_STRLEN(first); +	} +	return URI_FUNC(ParseSingleUriExMm)(uri, first, afterLast, errorPos, NULL); +} + + + +int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		const URI_CHAR ** errorPos, UriMemoryManager * memory) { +	URI_TYPE(ParserState) state; +	int res; + +	/* Check params */ +	if ((uri == NULL) || (first == NULL) || (afterLast == NULL)) { +		return URI_ERROR_NULL; +	} +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ + +	state.uri = uri; + +	res = URI_FUNC(ParseUriExMm)(&state, first, afterLast, memory); + +	if (res != URI_SUCCESS) { +		if (errorPos != NULL) { +			*errorPos = state.errorPos; +		} +		URI_FUNC(FreeUriMembersMm)(uri, memory); +	} + +	return res; +} + + +  void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) { +	URI_FUNC(FreeUriMembersMm)(uri, NULL); +} + + + +int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {  	if (uri == NULL) { -		return; +		return URI_ERROR_NULL;  	} +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ +  	if (uri->owner) {  		/* Scheme */  		if (uri->scheme.first != NULL) {  			if (uri->scheme.first != uri->scheme.afterLast) { -				free((URI_CHAR *)uri->scheme.first); +				memory->free(memory, (URI_CHAR *)uri->scheme.first);  			}  			uri->scheme.first = NULL;  			uri->scheme.afterLast = NULL; @@ -2116,7 +2262,7 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  		/* User info */  		if (uri->userInfo.first != NULL) {  			if (uri->userInfo.first != uri->userInfo.afterLast) { -				free((URI_CHAR *)uri->userInfo.first); +				memory->free(memory, (URI_CHAR *)uri->userInfo.first);  			}  			uri->userInfo.first = NULL;  			uri->userInfo.afterLast = NULL; @@ -2125,7 +2271,7 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  		/* Host data - IPvFuture */  		if (uri->hostData.ipFuture.first != NULL) {  			if (uri->hostData.ipFuture.first != uri->hostData.ipFuture.afterLast) { -				free((URI_CHAR *)uri->hostData.ipFuture.first); +				memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first);  			}  			uri->hostData.ipFuture.first = NULL;  			uri->hostData.ipFuture.afterLast = NULL; @@ -2139,7 +2285,7 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  				&& (uri->hostData.ip6 == NULL)) {  			/* Real regname */  			if (uri->hostText.first != uri->hostText.afterLast) { -				free((URI_CHAR *)uri->hostText.first); +				memory->free(memory, (URI_CHAR *)uri->hostText.first);  			}  			uri->hostText.first = NULL;  			uri->hostText.afterLast = NULL; @@ -2148,20 +2294,20 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  	/* Host data - IPv4 */  	if (uri->hostData.ip4 != NULL) { -		free(uri->hostData.ip4); +		memory->free(memory, uri->hostData.ip4);  		uri->hostData.ip4 = NULL;  	}  	/* Host data - IPv6 */  	if (uri->hostData.ip6 != NULL) { -		free(uri->hostData.ip6); +		memory->free(memory, uri->hostData.ip6);  		uri->hostData.ip6 = NULL;  	}  	/* Port text */  	if (uri->owner && (uri->portText.first != NULL)) {  		if (uri->portText.first != uri->portText.afterLast) { -			free((URI_CHAR *)uri->portText.first); +			memory->free(memory, (URI_CHAR *)uri->portText.first);  		}  		uri->portText.first = NULL;  		uri->portText.afterLast = NULL; @@ -2174,9 +2320,9 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  			URI_TYPE(PathSegment) * const next = segWalk->next;  			if (uri->owner && (segWalk->text.first != NULL)  					&& (segWalk->text.first < segWalk->text.afterLast)) { -				free((URI_CHAR *)segWalk->text.first); +				memory->free(memory, (URI_CHAR *)segWalk->text.first);  			} -			free(segWalk); +			memory->free(memory, segWalk);  			segWalk = next;  		}  		uri->pathHead = NULL; @@ -2187,7 +2333,7 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  		/* Query */  		if (uri->query.first != NULL) {  			if (uri->query.first != uri->query.afterLast) { -				free((URI_CHAR *)uri->query.first); +				memory->free(memory, (URI_CHAR *)uri->query.first);  			}  			uri->query.first = NULL;  			uri->query.afterLast = NULL; @@ -2196,17 +2342,20 @@ void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {  		/* Fragment */  		if (uri->fragment.first != NULL) {  			if (uri->fragment.first != uri->fragment.afterLast) { -				free((URI_CHAR *)uri->fragment.first); +				memory->free(memory, (URI_CHAR *)uri->fragment.first);  			}  			uri->fragment.first = NULL;  			uri->fragment.afterLast = NULL;  		}  	} + +	return URI_SUCCESS;  }  UriBool URI_FUNC(_TESTING_ONLY_ParseIpSix)(const URI_CHAR * text) { +	UriMemoryManager * const memory = &defaultMemoryManager;  	URI_TYPE(Uri) uri;  	URI_TYPE(ParserState) parser;  	const URI_CHAR * const afterIpSix = text + URI_STRLEN(text); @@ -2215,9 +2364,9 @@ UriBool URI_FUNC(_TESTING_ONLY_ParseIpSix)(const URI_CHAR * text) {  	URI_FUNC(ResetUri)(&uri);  	parser.uri = &uri;  	URI_FUNC(ResetParserStateExceptUri)(&parser); -	parser.uri->hostData.ip6 = malloc(1 * sizeof(UriIp6)); -	res = URI_FUNC(ParseIPv6address2)(&parser, text, afterIpSix); -	URI_FUNC(FreeUriMembers)(&uri); +	parser.uri->hostData.ip6 = memory->malloc(memory, 1 * sizeof(UriIp6)); +	res = URI_FUNC(ParseIPv6address2)(&parser, text, afterIpSix, memory); +	URI_FUNC(FreeUriMembersMm)(&uri, memory);  	return res == afterIpSix ? URI_TRUE : URI_FALSE;  } diff --git a/src/UriQuery.c b/src/UriQuery.c index f0cd4f8..326e963 100644 --- a/src/UriQuery.c +++ b/src/UriQuery.c @@ -64,10 +64,15 @@  #ifndef URI_DOXYGEN  # include <uriparser/Uri.h>  # include "UriCommon.h" +# include "UriMemory.h"  #endif +#include <limits.h> + + +  static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  		const URI_TYPE(QueryList) * queryList,  		int maxChars, int * charsWritten, int * charsRequired, @@ -76,7 +81,8 @@ static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  static UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  		int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter,  		const URI_CHAR * valueFirst, const URI_CHAR * valueAfter, -		UriBool plusToSpace, UriBreakConversion breakConversion); +		UriBool plusToSpace, UriBreakConversion breakConversion, +		UriMemoryManager * memory); @@ -145,6 +151,16 @@ int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest,  int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest,  		const URI_TYPE(QueryList) * queryList,  		UriBool spaceToPlus, UriBool normalizeBreaks) { +	return URI_FUNC(ComposeQueryMallocExMm)(dest, queryList, spaceToPlus, +			normalizeBreaks, NULL); +} + + + +int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest, +		const URI_TYPE(QueryList) * queryList, +		UriBool spaceToPlus, UriBool normalizeBreaks, +		UriMemoryManager * memory) {  	int charsRequired;  	int res;  	URI_CHAR * queryString; @@ -153,6 +169,8 @@ int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest,  		return URI_ERROR_NULL;  	} +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ +  	/* Calculate space */  	res = URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, &charsRequired,  			spaceToPlus, normalizeBreaks); @@ -162,7 +180,7 @@ int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest,  	charsRequired++;  	/* Allocate space */ -	queryString = malloc(charsRequired * sizeof(URI_CHAR)); +	queryString = memory->malloc(memory, charsRequired * sizeof(URI_CHAR));  	if (queryString == NULL) {  		return URI_ERROR_MALLOC;  	} @@ -171,7 +189,7 @@ int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest,  	res = URI_FUNC(ComposeQueryEx)(queryString, queryList, charsRequired,  			NULL, spaceToPlus, normalizeBreaks);  	if (res != URI_SUCCESS) { -		free(queryString); +		memory->free(memory, queryString);  		return res;  	} @@ -186,7 +204,7 @@ int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  		int maxChars, int * charsWritten, int * charsRequired,  		UriBool spaceToPlus, UriBool normalizeBreaks) {  	UriBool firstItem = URI_TRUE; -	int ampersandLen = 0; +	int ampersandLen = 0;  /* increased to 1 from second item on */  	URI_CHAR * write = dest;  	/* Subtract terminator */ @@ -195,46 +213,48 @@ int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  	} else {  		maxChars--;  	} -			 +  	while (queryList != NULL) {  		const URI_CHAR * const key = queryList->key;  		const URI_CHAR * const value = queryList->value;  		const int worstCase = (normalizeBreaks == URI_TRUE ? 6 : 3);  		const int keyLen = (key == NULL) ? 0 : (int)URI_STRLEN(key); -		const int keyRequiredChars = worstCase * keyLen; +		int keyRequiredChars;  		const int valueLen = (value == NULL) ? 0 : (int)URI_STRLEN(value); -		const int valueRequiredChars = worstCase * valueLen; +		int valueRequiredChars; + +		if ((keyLen >= INT_MAX / worstCase) || (valueLen >= INT_MAX / worstCase)) { +			return URI_ERROR_OUTPUT_TOO_LARGE; +		} +		keyRequiredChars = worstCase * keyLen; +		valueRequiredChars = worstCase * valueLen;  		if (dest == NULL) { +			(*charsRequired) += ampersandLen + keyRequiredChars + ((value == NULL) +						? 0 +						: 1 + valueRequiredChars); +  			if (firstItem == URI_TRUE) {  				ampersandLen = 1;  				firstItem = URI_FALSE;  			} - -			(*charsRequired) += ampersandLen + keyRequiredChars + ((value == NULL) -						? 0 -						: 1 + valueRequiredChars);  		} else { -			URI_CHAR * afterKey; -  			if ((write - dest) + ampersandLen + keyRequiredChars > maxChars) {  				return URI_ERROR_OUTPUT_TOO_LARGE;  			}  			/* Copy key */  			if (firstItem == URI_TRUE) { +				ampersandLen = 1;  				firstItem = URI_FALSE;  			} else {  				write[0] = _UT('&');  				write++;  			} -			afterKey = URI_FUNC(EscapeEx)(key, key + keyLen, +			write = URI_FUNC(EscapeEx)(key, key + keyLen,  					write, spaceToPlus, normalizeBreaks); -			write += (afterKey - write);  			if (value != NULL) { -				URI_CHAR * afterValue; -  				if ((write - dest) + 1 + valueRequiredChars > maxChars) {  					return URI_ERROR_OUTPUT_TOO_LARGE;  				} @@ -242,9 +262,8 @@ int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  				/* Copy value */  				write[0] = _UT('=');  				write++; -				afterValue = URI_FUNC(EscapeEx)(value, value + valueLen, +				write = URI_FUNC(EscapeEx)(value, value + valueLen,  						write, spaceToPlus, normalizeBreaks); -				write += (afterValue - write);  			}  		} @@ -266,7 +285,8 @@ int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,  UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  		int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter,  		const URI_CHAR * valueFirst, const URI_CHAR * valueAfter, -		UriBool plusToSpace, UriBreakConversion breakConversion) { +		UriBool plusToSpace, UriBreakConversion breakConversion, +		UriMemoryManager * memory) {  	const int keyLen = (int)(keyAfter - keyFirst);  	const int valueLen = (int)(valueAfter - valueFirst);  	URI_CHAR * key; @@ -281,7 +301,7 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  	}  	/* Append new empty item */ -	*prevNext = malloc(1 * sizeof(URI_TYPE(QueryList))); +	*prevNext = memory->malloc(memory, 1 * sizeof(URI_TYPE(QueryList)));  	if (*prevNext == NULL) {  		return URI_FALSE; /* Raises malloc error */  	} @@ -289,9 +309,9 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  	/* Fill key */ -	key = malloc((keyLen + 1) * sizeof(URI_CHAR)); +	key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR));  	if (key == NULL) { -		free(*prevNext); +		memory->free(memory, *prevNext);  		*prevNext = NULL;  		return URI_FALSE; /* Raises malloc error */  	} @@ -309,10 +329,10 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  	/* Fill value */  	if (valueFirst != NULL) { -		value = malloc((valueLen + 1) * sizeof(URI_CHAR)); +		value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR));  		if (value == NULL) { -			free(key); -			free(*prevNext); +			memory->free(memory, key); +			memory->free(memory, *prevNext);  			*prevNext = NULL;  			return URI_FALSE; /* Raises malloc error */  		} @@ -338,13 +358,22 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,  void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList) { +	URI_FUNC(FreeQueryListMm)(queryList, NULL); +} + + + +int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList, +		UriMemoryManager * memory) { +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */  	while (queryList != NULL) {  		URI_TYPE(QueryList) * nextBackup = queryList->next; -		free((URI_CHAR *)queryList->key); /* const cast */ -		free((URI_CHAR *)queryList->value); /* const cast */ -		free(queryList); +		memory->free(memory, (URI_CHAR *)queryList->key); /* const cast */ +		memory->free(memory, (URI_CHAR *)queryList->value); /* const cast */ +		memory->free(memory, queryList);  		queryList = nextBackup;  	} +	return URI_SUCCESS;  } @@ -363,6 +392,16 @@ int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, int * itemCount,  int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount,  		const URI_CHAR * first, const URI_CHAR * afterLast,  		UriBool plusToSpace, UriBreakConversion breakConversion) { +	return URI_FUNC(DissectQueryMallocExMm)(dest, itemCount, first, afterLast, +			plusToSpace, breakConversion, NULL); +} + + + +int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, int * itemCount, +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriBool plusToSpace, UriBreakConversion breakConversion, +		UriMemoryManager * memory) {  	const URI_CHAR * walk = first;  	const URI_CHAR * keyFirst = first;  	const URI_CHAR * keyAfter = NULL; @@ -380,6 +419,8 @@ int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount,  		return URI_ERROR_RANGE_INVALID;  	} +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ +  	*dest = NULL;  	*itemsAppended = 0; @@ -395,11 +436,11 @@ int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount,  			if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended,  					keyFirst, keyAfter, valueFirst, valueAfter, -					plusToSpace, breakConversion) +					plusToSpace, breakConversion, memory)  					== URI_FALSE) {  				/* Free list we built */  				*itemsAppended = 0; -				URI_FUNC(FreeQueryList)(*dest); +				URI_FUNC(FreeQueryListMm)(*dest, memory);  				return URI_ERROR_MALLOC;  			} @@ -444,11 +485,11 @@ int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount,  	}  	if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, keyFirst, keyAfter, -			valueFirst, valueAfter, plusToSpace, breakConversion) +			valueFirst, valueAfter, plusToSpace, breakConversion, memory)  			== URI_FALSE) {  		/* Free list we built */  		*itemsAppended = 0; -		URI_FUNC(FreeQueryList)(*dest); +		URI_FUNC(FreeQueryListMm)(*dest, memory);  		return URI_ERROR_MALLOC;  	} diff --git a/src/UriResolve.c b/src/UriResolve.c index bb1d21a..6569819 100644 --- a/src/UriResolve.c +++ b/src/UriResolve.c @@ -64,6 +64,7 @@  #ifndef URI_DOXYGEN  # include <uriparser/Uri.h>  # include "UriCommon.h" +# include "UriMemory.h"  #endif @@ -71,7 +72,7 @@  /* Appends a relative URI to an absolute. The last path segment of   * the absolute URI is replaced. */  static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork, -		const URI_TYPE(Uri) * relAppend) { +		const URI_TYPE(Uri) * relAppend, UriMemoryManager * memory) {  	URI_TYPE(PathSegment) * sourceWalker;  	URI_TYPE(PathSegment) * destPrev;  	if (relAppend->pathHead == NULL) { @@ -80,7 +81,7 @@ static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork,  	/* Replace last segment ("" if trailing slash) with first of append chain */  	if (absWork->pathHead == NULL) { -		URI_TYPE(PathSegment) * const dup = malloc(sizeof(URI_TYPE(PathSegment))); +		URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));  		if (dup == NULL) {  			return URI_FALSE; /* Raises malloc error */  		} @@ -99,7 +100,7 @@ static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork,  	destPrev = absWork->pathTail;  	for (;;) { -		URI_TYPE(PathSegment) * const dup = malloc(sizeof(URI_TYPE(PathSegment))); +		URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));  		if (dup == NULL) {  			destPrev->next = NULL;  			absWork->pathTail = destPrev; @@ -121,7 +122,8 @@ static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork,  } -static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork) { +static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork, +		UriMemoryManager * memory) {  	if (absWork == NULL) {  		return URI_ERROR_NULL;  	} @@ -129,7 +131,7 @@ static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork) {  	if (URI_FUNC(IsHostSet)(absWork) && absWork->absolutePath) {  		/* Empty segment needed, instead? */  		if (absWork->pathHead == NULL) { -			URI_TYPE(PathSegment) * const segment = malloc(sizeof(URI_TYPE(PathSegment))); +			URI_TYPE(PathSegment) * const segment = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));  			if (segment == NULL) {  				return URI_ERROR_MALLOC;  			} @@ -151,7 +153,7 @@ static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork) {  static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  		const URI_TYPE(Uri) * relSource,  		const URI_TYPE(Uri) * absBase, -		UriResolutionOptions options) { +		UriResolutionOptions options, UriMemoryManager * memory) {  	UriBool relSourceHasScheme;  	if (absDest == NULL) { @@ -186,14 +188,14 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  	/* [02/32]		T.scheme = R.scheme; */  					absDest->scheme = relSource->scheme;  	/* [03/32]		T.authority = R.authority; */ -					if (!URI_FUNC(CopyAuthority)(absDest, relSource)) { +					if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) {  						return URI_ERROR_MALLOC;  					}  	/* [04/32]		T.path = remove_dot_segments(R.path); */ -					if (!URI_FUNC(CopyPath)(absDest, relSource)) { +					if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {  						return URI_ERROR_MALLOC;  					} -					if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest)) { +					if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {  						return URI_ERROR_MALLOC;  					}  	/* [05/32]		T.query = R.query; */ @@ -203,14 +205,14 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  	/* [07/32]		if defined(R.authority) then */  					if (URI_FUNC(IsHostSet)(relSource)) {  	/* [08/32]			T.authority = R.authority; */ -						if (!URI_FUNC(CopyAuthority)(absDest, relSource)) { +						if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) {  							return URI_ERROR_MALLOC;  						}  	/* [09/32]			T.path = remove_dot_segments(R.path); */ -						if (!URI_FUNC(CopyPath)(absDest, relSource)) { +						if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {  							return URI_ERROR_MALLOC;  						} -						if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest)) { +						if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {  							return URI_ERROR_MALLOC;  						}  	/* [10/32]			T.query = R.query; */ @@ -218,13 +220,13 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  	/* [11/32]		else */  					} else {  	/* [28/32]			T.authority = Base.authority; */ -						if (!URI_FUNC(CopyAuthority)(absDest, absBase)) { +						if (!URI_FUNC(CopyAuthority)(absDest, absBase, memory)) {  							return URI_ERROR_MALLOC;  						}  	/* [12/32]			if (R.path == "") then */  						if (relSource->pathHead == NULL && !relSource->absolutePath) {  	/* [13/32]				T.path = Base.path; */ -							if (!URI_FUNC(CopyPath)(absDest, absBase)) { +							if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) {  								return URI_ERROR_MALLOC;  							}  	/* [14/32]				if defined(R.query) then */ @@ -243,31 +245,31 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  							if (relSource->absolutePath) {  								int res;  	/* [21/32]					T.path = remove_dot_segments(R.path); */ -								if (!URI_FUNC(CopyPath)(absDest, relSource)) { +								if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {  									return URI_ERROR_MALLOC;  								} -								res = URI_FUNC(ResolveAbsolutePathFlag)(absDest); +								res = URI_FUNC(ResolveAbsolutePathFlag)(absDest, memory);  								if (res != URI_SUCCESS) {  									return res;  								} -								if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest)) { +								if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {  									return URI_ERROR_MALLOC;  								}  	/* [22/32]				else */  							} else {  	/* [23/32]					T.path = merge(Base.path, R.path); */ -								if (!URI_FUNC(CopyPath)(absDest, absBase)) { +								if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) {  									return URI_ERROR_MALLOC;  								} -								if (!URI_FUNC(MergePath)(absDest, relSource)) { +								if (!URI_FUNC(MergePath)(absDest, relSource, memory)) {  									return URI_ERROR_MALLOC;  								}  	/* [24/32]					T.path = remove_dot_segments(T.path); */ -								if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest)) { +								if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {  									return URI_ERROR_MALLOC;  								} -								if (!URI_FUNC(FixAmbiguity)(absDest)) { +								if (!URI_FUNC(FixAmbiguity)(absDest, memory)) {  									return URI_ERROR_MALLOC;  								}  	/* [25/32]				endif; */ @@ -276,7 +278,7 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  							absDest->query = relSource->query;  	/* [27/32]			endif; */  						} -						URI_FUNC(FixEmptyTrailSegment)(absDest); +						URI_FUNC(FixEmptyTrailSegment)(absDest, memory);  	/* [29/32]		endif; */  					}  	/* [30/32]		T.scheme = Base.scheme; */ @@ -294,11 +296,8 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,  int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absDest,  		const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase) { -	const int res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, URI_RESOLVE_STRICTLY); -	if ((res != URI_SUCCESS) && (absDest != NULL)) { -		URI_FUNC(FreeUriMembers)(absDest); -	} -	return res; +	const UriResolutionOptions options = URI_RESOLVE_STRICTLY; +	return URI_FUNC(AddBaseUriEx)(absDest, relSource, absBase, options);  } @@ -306,9 +305,21 @@ int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absDest,  int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absDest,  		const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase,  		UriResolutionOptions options) { -	const int res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, options); +	return URI_FUNC(AddBaseUriExMm)(absDest, relSource, absBase, options, NULL); +} + + + +int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absDest, +		const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase, +		UriResolutionOptions options, UriMemoryManager * memory) { +	int res; + +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ + +	res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, options, memory);  	if ((res != URI_SUCCESS) && (absDest != NULL)) { -		URI_FUNC(FreeUriMembers)(absDest); +		URI_FUNC(FreeUriMembersMm)(absDest, memory);  	}  	return res;  } diff --git a/src/UriShorten.c b/src/UriShorten.c index e7f6df4..7b0bc97 100644 --- a/src/UriShorten.c +++ b/src/UriShorten.c @@ -64,14 +64,16 @@  #ifndef URI_DOXYGEN  # include <uriparser/Uri.h>  # include "UriCommon.h" +# include "UriMemory.h"  #endif  static URI_INLINE UriBool URI_FUNC(AppendSegment)(URI_TYPE(Uri) * uri, -		const URI_CHAR * first, const URI_CHAR * afterLast) { +		const URI_CHAR * first, const URI_CHAR * afterLast, +		UriMemoryManager * memory) {  	/* Create segment */ -	URI_TYPE(PathSegment) * segment = malloc(1 * sizeof(URI_TYPE(PathSegment))); +	URI_TYPE(PathSegment) * segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));  	if (segment == NULL) {  		return URI_FALSE; /* Raises malloc error */  	} @@ -124,7 +126,7 @@ static URI_INLINE UriBool URI_FUNC(EqualsAuthority)(const URI_TYPE(Uri) * first,  static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  		const URI_TYPE(Uri) * absSource,  		const URI_TYPE(Uri) * absBase, -		UriBool domainRootMode) { +		UriBool domainRootMode, UriMemoryManager * memory) {  	if (dest == NULL) {  		return URI_ERROR_NULL;  	} @@ -149,11 +151,11 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  	/* [02/50]	   T.scheme    = A.scheme; */  					dest->scheme = absSource->scheme;  	/* [03/50]	   T.authority = A.authority; */ -					if (!URI_FUNC(CopyAuthority)(dest, absSource)) { +					if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) {  						return URI_ERROR_MALLOC;  					}  	/* [04/50]	   T.path      = A.path; */ -					if (!URI_FUNC(CopyPath)(dest, absSource)) { +					if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {  						return URI_ERROR_MALLOC;  					}  	/* [05/50]	else */ @@ -163,11 +165,11 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  	/* [07/50]	   if (A.authority != Base.authority) then */  					if (!URI_FUNC(EqualsAuthority)(absSource, absBase)) {  	/* [08/50]	      T.authority = A.authority; */ -						if (!URI_FUNC(CopyAuthority)(dest, absSource)) { +						if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) {  							return URI_ERROR_MALLOC;  						}  	/* [09/50]	      T.path      = A.path; */ -						if (!URI_FUNC(CopyPath)(dest, absSource)) { +						if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {  							return URI_ERROR_MALLOC;  						}  	/* [10/50]	   else */ @@ -185,12 +187,12 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  	/* [16/50]	            T.path   = A.path; */  								/* GROUPED */  	/* [17/50]	         endif; */ -							if (!URI_FUNC(CopyPath)(dest, absSource)) { +							if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {  								return URI_ERROR_MALLOC;  							}  							dest->absolutePath = URI_TRUE; -							if (!URI_FUNC(FixAmbiguity)(dest)) { +							if (!URI_FUNC(FixAmbiguity)(dest, memory)) {  								return URI_ERROR_MALLOC;  							}  	/* [18/50]	      else */ @@ -220,7 +222,7 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  								baseSeg = baseSeg->next;  	/* [28/50]	            T.path += "../"; */  								if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstParent), -										URI_FUNC(ConstParent) + 2)) { +										URI_FUNC(ConstParent) + 2, memory)) {  									return URI_ERROR_MALLOC;  								}  	/* [29/50]	            pathNaked = false; */ @@ -244,14 +246,14 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  									if (containsColon) {  	/* [34/50]	                  T.path += "./"; */  										if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), -												URI_FUNC(ConstPwd) + 1)) { +												URI_FUNC(ConstPwd) + 1, memory)) {  											return URI_ERROR_MALLOC;  										}  	/* [35/50]	               elseif (first(A.path) == "") then */  									} else if (sourceSeg->text.first == sourceSeg->text.afterLast) {  	/* [36/50]	                  T.path += "/."; */  										if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), -												URI_FUNC(ConstPwd) + 1)) { +												URI_FUNC(ConstPwd) + 1, memory)) {  											return URI_ERROR_MALLOC;  										}  	/* [37/50]	               endif; */ @@ -260,7 +262,7 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,  								}  	/* [39/50]	            T.path += first(A.path); */  								if (!URI_FUNC(AppendSegment)(dest, sourceSeg->text.first, -										sourceSeg->text.afterLast)) { +										sourceSeg->text.afterLast, memory)) {  									return URI_ERROR_MALLOC;  								}  	/* [40/50]	            pathNaked = false; */ @@ -295,10 +297,24 @@ int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest,  		const URI_TYPE(Uri) * absSource,  		const URI_TYPE(Uri) * absBase,  		UriBool domainRootMode) { -	const int res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource, -			absBase, domainRootMode); +	return URI_FUNC(RemoveBaseUriMm)(dest, absSource, absBase, +			domainRootMode, NULL); +} + + + +int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, +		const URI_TYPE(Uri) * absSource, +		const URI_TYPE(Uri) * absBase, +		UriBool domainRootMode, UriMemoryManager * memory) { +	int res; + +	URI_CHECK_MEMORY_MANAGER(memory);  /* may return */ + +	res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource, +			absBase, domainRootMode, memory);  	if ((res != URI_SUCCESS) && (dest != NULL)) { -		URI_FUNC(FreeUriMembers)(dest); +		URI_FUNC(FreeUriMembersMm)(dest, memory);  	}  	return res;  } | 
