Fossil SCM
Only decode '%' in urls if followed by exactly 2 hex digits, eg '%zz' mid-url no longer decoded as null. From libfossil.
Commit
399a624524b6c9c645c7def9e8b76584fa6c2adc6694bc6896c0ce6db9e777d9
Parent
7e13ac5c4efbe16…
1 file changed
+7
-2
+7
-2
| --- src/encode.c | ||
| +++ src/encode.c | ||
| @@ -331,26 +331,31 @@ | ||
| 331 | 331 | return c; |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | /* |
| 335 | 335 | ** 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). | |
| 337 | 338 | */ |
| 338 | 339 | int dehttpize(char *z){ |
| 340 | + static const char zHex[] = "0123456789abcdefABCDEF"; | |
| 339 | 341 | int i, j; |
| 340 | 342 | |
| 341 | 343 | /* Treat a null pointer as a zero-length string. */ |
| 342 | 344 | if( !z ) return 0; |
| 343 | 345 | |
| 344 | 346 | i = j = 0; |
| 345 | 347 | while( z[i] ){ |
| 346 | 348 | switch( z[i] ){ |
| 347 | 349 | 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]) ){ | |
| 349 | 352 | z[j] = fossil_hexvalue(z[i+1]) << 4; |
| 350 | 353 | z[j] |= fossil_hexvalue(z[i+2]); |
| 351 | 354 | i += 2; |
| 355 | + }else{ | |
| 356 | + z[j] = '%'; | |
| 352 | 357 | } |
| 353 | 358 | break; |
| 354 | 359 | case '+': |
| 355 | 360 | z[j] = ' '; |
| 356 | 361 | break; |
| 357 | 362 |
| --- 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 |