Skip to content

Commit 1ca78dd

Browse files
authored
uri: Update to uriparser-0.9.9-21-g08df3b2 (php#19992)
This is specifically to backport uriparser/uriparser#265. Fixes php#19897.
1 parent 7858a83 commit 1ca78dd

File tree

6 files changed

+130
-38
lines changed

6 files changed

+130
-38
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PHP NEWS
3535
(timwolla)
3636
. Fixed Uri\WhatWg\Url::parse() when resolving a relative URL
3737
against a base URL with query or fragment. (timwolla)
38+
. Fixed normalization of paths starting with two slashes for
39+
Uri\Rfc3986\Uri. (timwolla)
3840

3941
25 Sep 2025, PHP 8.5.0RC1
4042

ext/uri/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if test "$PHP_EXTERNAL_URIPARSER" = "no"; then
3333
$URIPARSER_DIR/src/UriSetScheme.c $URIPARSER_DIR/src/UriSetUserInfo.c $URIPARSER_DIR/src/UriShorten.c $URIPARSER_DIR/src/UriVersion.c"
3434
URI_CFLAGS="-DURI_STATIC_BUILD"
3535
else
36-
PKG_CHECK_MODULES([LIBURIPARSER], [liburiparser >= 0.9.9])
36+
PKG_CHECK_MODULES([LIBURIPARSER], [liburiparser >= 0.9.10])
3737
PHP_EVAL_LIBLINE([$LIBURIPARSER_LIBS], [URI_SHARED_LIBADD])
3838
PHP_EVAL_INCLINE([$LIBURIPARSER_CFLAGS])
3939
fi

ext/uri/uriparser/include/uriparser/Uri.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ typedef struct URI_TYPE(HostDataStruct) {
137137
URI_TYPE(TextRange) ipFuture; /**< IPvFuture address
138138
@note
139139
With non-<c>NULL</c> members in UriUriStructA.hostData context,
140-
this text range's pointers must be <em>idential</em> to those
140+
this text range's pointers must be <em>identical</em> to those
141141
of UriUriStructA.hostText at all times. */
142142
} URI_TYPE(HostData); /**< @copydoc UriHostDataStructA */
143143

@@ -1420,7 +1420,7 @@ URI_PUBLIC UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, con
14201420
*
14211421
* @param first <b>IN</b>: Pointer to first character
14221422
* @param afterLast <b>IN</b>: Pointer to character after the last one still in
1423-
* @param hasHost <b>IN</b>: Wether the target %URI has a non-<c>NULL</c> host set or not
1423+
* @param hasHost <b>IN</b>: Whether the target %URI has a non-<c>NULL</c> host set or not
14241424
* @return <c>URI_TRUE</c> if non-<c>NULL</c> and well-formed, else <c>URI_FALSE</c>
14251425
*
14261426
* @see uriIsWellFormedFragmentA
@@ -2415,7 +2415,7 @@ URI_PUBLIC int URI_FUNC(SetUserInfoMm)(URI_TYPE(Uri) * uri,
24152415
* or even fully custom patches. As a result, the version string
24162416
* returned serves as nothing more than "based on that version",
24172417
* it does not guarantee equivalence to vanilla upstream releases
2418-
* or absence of additinal downstream patches.
2418+
* or absence of additional downstream patches.
24192419
* It is nothing more than "a hint" and MUST NEVER be used to
24202420
* make decisions on in application code at runtime.
24212421
*

ext/uri/uriparser/include/uriparser/UriBase.h

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ typedef struct UriIp6Struct {
187187
} UriIp6; /**< @copydoc UriIp6Struct */
188188

189189

190-
struct UriMemoryManagerStruct; /* foward declaration to break loop */
190+
struct UriMemoryManagerStruct; /* forward declaration to break loop */
191191

192192

193193
/**
@@ -287,28 +287,34 @@ typedef enum UriResolutionOptionsEnum {
287287

288288

289289
/**
290-
* Wraps a memory manager backend that only provides malloc and free
291-
* to make a complete memory manager ready to be used.
290+
* Wraps a memory manager backend that only provides <c>malloc(3)</c> and
291+
* <c>free(3)</c> to make a complete memory manager ready to be used.
292292
*
293293
* The core feature of this wrapper is that you don't need to implement
294-
* realloc if you don't want to. The wrapped memory manager uses
295-
* backend->malloc, memcpy, and backend->free and soieof(size_t) extra
296-
* bytes per allocation to emulate fallback realloc for you.
294+
* <c>realloc(3)</c> if you don't want to. The wrapped memory manager uses
295+
* <c>backend-&gt;malloc</c>, <c>memcpy(3)</c>, and <c>backend-&gt;free</c> and
296+
* (at least) <c>sizeof(size_t)</c> extra bytes per allocation to emulate
297+
* fallback <c>realloc(3)</c> for you.
297298
*
298-
* memory->calloc is uriEmulateCalloc.
299-
* memory->free uses backend->free and handles the size header.
300-
* memory->malloc uses backend->malloc and adds a size header.
301-
* memory->realloc uses memory->malloc, memcpy, and memory->free and reads
302-
* the size header.
303-
* memory->reallocarray is uriEmulateReallocarray.
299+
* <ul>
300+
* <li><c>memory-&gt;calloc</c> is <c>uriEmulateCalloc</c>.</li>
301+
* <li><c>memory-&gt;free</c> uses <c>backend-&gt;free</c>,
302+
* and handles the size header.</li>
303+
* <li><c>memory-&gt;malloc</c> uses <c>backend-&gt;malloc</c>,
304+
* and adds a size header.</li>
305+
* <li><c>memory-&gt;realloc</c> uses <c>memory-&gt;malloc</c>,
306+
* <c>memcpy(3)</c> and <c>memory-&gt;free</c>,
307+
* and reads the size header.</li>
308+
* <li><c>memory-&gt;reallocarray</c> is <c>uriEmulateReallocarray</c>.</li>
309+
* </ul>
304310
*
305-
* The internal workings behind memory->free, memory->malloc, and
306-
* memory->realloc may change so the functions exposed by these function
307-
* pointer sshould be consided internal and not public API.
311+
* The internal workings behind <c>memory-&gt;free</c>, <c>memory-&gt;malloc</c>,
312+
* and <c>memory-&gt;realloc</c> may change, and the functions exposed by these
313+
* function pointers should be considered internal and not public API.
308314
*
309315
* @param memory <b>OUT</b>: Where to write the wrapped memory manager to
310316
* @param backend <b>IN</b>: Memory manager to use as a backend
311-
* @return Error code or 0 on success
317+
* @return Error code or 0 on success
312318
*
313319
* @see uriEmulateCalloc
314320
* @see uriEmulateReallocarray
@@ -321,7 +327,7 @@ URI_PUBLIC int uriCompleteMemoryManager(UriMemoryManager * memory,
321327

322328

323329
/**
324-
* Offers emulation of calloc(3) based on memory->malloc and memset.
330+
* Offers emulation of calloc(3) based on memory-&gt;malloc and memset.
325331
* See "man 3 calloc" as well.
326332
*
327333
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
@@ -340,11 +346,11 @@ URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory,
340346

341347

342348
/**
343-
* Offers emulation of reallocarray(3) based on memory->realloc.
349+
* Offers emulation of reallocarray(3) based on memory-&gt;realloc.
344350
* See "man 3 reallocarray" as well.
345351
*
346352
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
347-
* @param ptr <b>IN</b>: Pointer allocated using memory->malloc/... or NULL
353+
* @param ptr <b>IN</b>: Pointer allocated using memory-&gt;malloc/... or NULL
348354
* @param nmemb <b>IN</b>: Number of elements to allocate
349355
* @param size <b>IN</b>: Size in bytes per element
350356
* @return Pointer to allocated memory or NULL
@@ -369,18 +375,52 @@ URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory,
369375
* 5. and frees that memory.
370376
*
371377
* It is recommended to compile with AddressSanitizer enabled
372-
* to take full advantage of uriTestMemoryManager.
378+
* to take full advantage of <c>uriTestMemoryManager</c>.
379+
*
380+
* For backwards-compatibility, <c>uriTestMemoryManager</c>
381+
* does not challenge pointer alignment; please see
382+
* <c>uriTestMemoryManagerEx</c> for that feature.
373383
*
374384
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
375385
* @return Error code or 0 on success
376386
*
377387
* @see uriEmulateCalloc
378388
* @see uriEmulateReallocarray
379389
* @see UriMemoryManager
390+
* @see uriTestMemoryManagerEx
380391
* @since 0.9.0
381392
*/
382393
URI_PUBLIC int uriTestMemoryManager(UriMemoryManager * memory);
383394

384395

385396

397+
/**
398+
* Run multiple tests against a given memory manager.
399+
* For example, one test
400+
* 1. allocates a small amount of memory,
401+
* 2. writes some magic bytes to it,
402+
* 3. reallocates it,
403+
* 4. checks that previous values are still present,
404+
* 5. and frees that memory.
405+
*
406+
* It is recommended to compile with both AddressSanitizer and
407+
* UndefinedBehaviorSanitizer enabled to take full advantage of
408+
* <c>uriTestMemoryManagerEx</c>. Note that environment variable
409+
* <c>UBSAN_OPTIONS</c> may need adjustment to make UndefinedBehaviorSanitizer
410+
* fatal (which by default it is not).
411+
*
412+
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
413+
* @param challengeAlignment <b>IN</b>: Whether to challenge pointer alignment
414+
* @return Error code or 0 on success
415+
*
416+
* @see uriEmulateCalloc
417+
* @see uriEmulateReallocarray
418+
* @see UriMemoryManager
419+
* @see uriTestMemoryManager
420+
* @since 0.9.10
421+
*/
422+
URI_PUBLIC int uriTestMemoryManagerEx(UriMemoryManager * memory, UriBool challengeAlignment);
423+
424+
425+
386426
#endif /* URI_BASE_H */

ext/uri/uriparser/src/UriCommon.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,25 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
208208
*
209209
* For example, changing "./http://foo" into "http://foo" would change semantics
210210
* and hence the dot segment is essential to that case and cannot be removed.
211+
*
212+
* Other examples that would change semantics are:
213+
* - cutting "/.//" down to "//"
214+
* - cutting "scheme:/.//" down to "scheme://".
211215
*/
212216
removeSegment = URI_TRUE;
213-
if (relative && (walker == uri->pathHead) && (walker->next != NULL)) {
214-
const URI_CHAR * ch = walker->next->text.first;
215-
for (; ch < walker->next->text.afterLast; ch++) {
216-
if (*ch == _UT(':')) {
217-
removeSegment = URI_FALSE;
218-
break;
217+
if ((walker == uri->pathHead) && (walker->next != NULL)) {
218+
/* Detect case "/.//" (with or without scheme) */
219+
if ((walker->next->text.first == walker->next->text.afterLast)
220+
&& (URI_FUNC(HasHost)(uri) == URI_FALSE)) {
221+
removeSegment = URI_FALSE;
222+
/* Detect case "./withcolon:" */
223+
} else if (relative) {
224+
const URI_CHAR * ch = walker->next->text.first;
225+
for (; ch < walker->next->text.afterLast; ch++) {
226+
if (*ch == _UT(':')) {
227+
removeSegment = URI_FALSE;
228+
break;
229+
}
219230
}
220231
}
221232
}
@@ -358,7 +369,7 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
358369
}
359370
memory->free(memory, walker);
360371
} else {
361-
/* Re-use segment for "" path segment to represent trailing slash, update tail */
372+
/* Reuse segment for "" path segment to represent trailing slash, update tail */
362373
URI_TYPE(PathSegment) * const segment = walker;
363374
if (pathOwned && (segment->text.first != segment->text.afterLast)) {
364375
memory->free(memory, (URI_CHAR *)segment->text.first);
@@ -403,7 +414,7 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
403414
* NEW: tail -> NULL */
404415
uri->pathTail = NULL;
405416
} else {
406-
/* Re-use segment for "" path segment to represent trailing slash,
417+
/* Reuse segment for "" path segment to represent trailing slash,
407418
* then update head and tail */
408419
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
409420
memory->free(memory, (URI_CHAR *)walker->text.first);
@@ -696,7 +707,7 @@ static UriBool URI_FUNC(PrependNewDotSegment)(URI_TYPE(Uri) * uri, UriMemoryMana
696707
/* When dropping a scheme from a URI without a host and with a colon (":")
697708
* in the first path segment, a consecutive reparse would rightfully
698709
* mis-classify the first path segment as a scheme due to the colon.
699-
* To protect against this case, we prepend an artifical "." segment
710+
* To protect against this case, we prepend an artificial "." segment
700711
* to the path in here; the function is called after the scheme has
701712
* just been dropped.
702713
*
@@ -751,7 +762,7 @@ UriBool URI_FUNC(FixPathNoScheme)(URI_TYPE(Uri) * uri,
751762
/* When dropping a host from a URI without a scheme, an absolute path
752763
* and and empty first path segment, a consecutive reparse would rightfully
753764
* mis-classify the first path segment as a host marker due to the "//".
754-
* To protect against this case, we prepend an artifical "." segment
765+
* To protect against this case, we prepend an artificial "." segment
755766
* to the path in here; the function is called after the host has
756767
* just been dropped.
757768
*

ext/uri/uriparser/src/UriMemory.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@
6464

6565

6666

67+
#define URI_MAX(a, b) (((a) > (b)) ? (a) : (b))
68+
69+
/* NOTE: This intends to mimic MALLOC_ALIGNMENT of glibc */
70+
#define URI_MALLOC_ALIGNMENT URI_MAX(2 * sizeof(size_t), sizeof(long double))
71+
72+
#define URI_MALLOC_PADDING (URI_MALLOC_ALIGNMENT - sizeof(size_t))
73+
74+
75+
6776
#define URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size) \
6877
do { \
6978
/* check for unsigned overflow */ \
@@ -170,7 +179,7 @@ void * uriEmulateReallocarray(UriMemoryManager * memory,
170179
static void * uriDecorateMalloc(UriMemoryManager * memory,
171180
size_t size) {
172181
UriMemoryManager * backend;
173-
const size_t extraBytes = sizeof(size_t);
182+
const size_t extraBytes = sizeof(size_t) + URI_MALLOC_PADDING;
174183
void * buffer;
175184

176185
if (memory == NULL) {
@@ -225,7 +234,7 @@ static void * uriDecorateRealloc(UriMemoryManager * memory,
225234
return NULL;
226235
}
227236

228-
prevSize = *((size_t *)((char *)ptr - sizeof(size_t)));
237+
prevSize = *((size_t *)((char *)ptr - sizeof(size_t) - URI_MALLOC_PADDING));
229238

230239
/* Anything to do? */
231240
if (size <= prevSize) {
@@ -259,7 +268,7 @@ static void uriDecorateFree(UriMemoryManager * memory, void * ptr) {
259268
return;
260269
}
261270

262-
backend->free(backend, (char *)ptr - sizeof(size_t));
271+
backend->free(backend, (char *)ptr - sizeof(size_t) - URI_MALLOC_PADDING);
263272
}
264273

265274

@@ -288,7 +297,7 @@ int uriCompleteMemoryManager(UriMemoryManager * memory,
288297

289298

290299

291-
int uriTestMemoryManager(UriMemoryManager * memory) {
300+
int uriTestMemoryManagerEx(UriMemoryManager * memory, UriBool challengeAlignment) {
292301
const size_t mallocSize = 7;
293302
const size_t callocNmemb = 3;
294303
const size_t callocSize = 5;
@@ -456,11 +465,41 @@ int uriTestMemoryManager(UriMemoryManager * memory) {
456465
buffer = NULL;
457466
}
458467

468+
/* challenge pointer alignment */
469+
if (challengeAlignment == URI_TRUE) {
470+
long double * ptr = memory->malloc(memory, 4 * sizeof(long double));
471+
if (ptr != NULL) {
472+
ptr[0] = 0.0L;
473+
ptr[1] = 1.1L;
474+
ptr[2] = 2.2L;
475+
ptr[3] = 3.3L;
476+
477+
{
478+
long double * const ptrNew = memory->realloc(memory, ptr, 8 * sizeof(long double));
479+
if (ptrNew != NULL) {
480+
ptr = ptrNew;
481+
ptr[4] = 4.4L;
482+
ptr[5] = 5.5L;
483+
ptr[6] = 6.6L;
484+
ptr[7] = 7.7L;
485+
}
486+
}
487+
488+
memory->free(memory, ptr);
489+
}
490+
}
491+
459492
return URI_SUCCESS;
460493
}
461494

462495

463496

497+
int uriTestMemoryManager(UriMemoryManager * memory) {
498+
return uriTestMemoryManagerEx(memory, /*challengeAlignment=*/ URI_FALSE);
499+
}
500+
501+
502+
464503
/*extern*/ UriMemoryManager defaultMemoryManager = {
465504
uriDefaultMalloc,
466505
uriDefaultCalloc,

0 commit comments

Comments
 (0)