Fossil SCM

Only decode '%' in urls if followed by exactly 2 hex digits, eg '%zz' mid-url no longer decoded as null. From libfossil.

danshearer 2026-10-12 11:00 UTC trunk
Commit 399a624524b6c9c645c7def9e8b76584fa6c2adc6694bc6896c0ce6db9e777d9
1 file changed +7 -2
+7 -2
--- src/encode.c
+++ src/encode.c
@@ -331,26 +331,31 @@
331331
return c;
332332
}
333333
334334
/*
335335
** Remove the HTTP encodings from a string. The conversion is done
336
-** in-place. Return the length of the string after conversion.
336
+** in-place. Return the length of the string after conversion. Only
337
+** decode '%' if it is followed by two hex digits (RFC 3986 section 2.1).
337338
*/
338339
int dehttpize(char *z){
340
+ static const char zHex[] = "0123456789abcdefABCDEF";
339341
int i, j;
340342
341343
/* Treat a null pointer as a zero-length string. */
342344
if( !z ) return 0;
343345
344346
i = j = 0;
345347
while( z[i] ){
346348
switch( z[i] ){
347349
case '%':
348
- if( z[i+1] && z[i+2] ){
350
+ if( z[i+1] && strchr(zHex, z[i+1])
351
+ && z[i+2] && strchr(zHex, z[i+2]) ){
349352
z[j] = fossil_hexvalue(z[i+1]) << 4;
350353
z[j] |= fossil_hexvalue(z[i+2]);
351354
i += 2;
355
+ }else{
356
+ z[j] = '%';
352357
}
353358
break;
354359
case '+':
355360
z[j] = ' ';
356361
break;
357362
--- src/encode.c
+++ src/encode.c
@@ -331,26 +331,31 @@
331 return c;
332 }
333
334 /*
335 ** Remove the HTTP encodings from a string. The conversion is done
336 ** in-place. Return the length of the string after conversion.
 
337 */
338 int dehttpize(char *z){
 
339 int i, j;
340
341 /* Treat a null pointer as a zero-length string. */
342 if( !z ) return 0;
343
344 i = j = 0;
345 while( z[i] ){
346 switch( z[i] ){
347 case '%':
348 if( z[i+1] && z[i+2] ){
 
349 z[j] = fossil_hexvalue(z[i+1]) << 4;
350 z[j] |= fossil_hexvalue(z[i+2]);
351 i += 2;
 
 
352 }
353 break;
354 case '+':
355 z[j] = ' ';
356 break;
357
--- src/encode.c
+++ src/encode.c
@@ -331,26 +331,31 @@
331 return c;
332 }
333
334 /*
335 ** Remove the HTTP encodings from a string. The conversion is done
336 ** in-place. Return the length of the string after conversion. Only
337 ** decode '%' if it is followed by two hex digits (RFC 3986 section 2.1).
338 */
339 int dehttpize(char *z){
340 static const char zHex[] = "0123456789abcdefABCDEF";
341 int i, j;
342
343 /* Treat a null pointer as a zero-length string. */
344 if( !z ) return 0;
345
346 i = j = 0;
347 while( z[i] ){
348 switch( z[i] ){
349 case '%':
350 if( z[i+1] && strchr(zHex, z[i+1])
351 && z[i+2] && strchr(zHex, z[i+2]) ){
352 z[j] = fossil_hexvalue(z[i+1]) << 4;
353 z[j] |= fossil_hexvalue(z[i+2]);
354 i += 2;
355 }else{
356 z[j] = '%';
357 }
358 break;
359 case '+':
360 z[j] = ' ';
361 break;
362

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button