Fossil SCM

Make <code>style_set_base_href_suffix()</code> safe for misuse: if the resulting suffix contains unescaped quotes then escape them. <var>$base_href_suffix</var> is intended for interpolation inside of the quoted href attribute. This check-in should address the case when a user of malfunctioning browser (which mishandles quoting) is tricked by an adversary to visit a specially crafted hyperlink.

george 2022-02-14 22:43 base-href-fix
Commit d97752f30b40a495de6f7954b58ec64e1454e55f354ff6fd6e0369beeb679044
2 files changed +30 +7 -3
+30
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205205
** by this routine.
206206
*/
207207
char *urlize(const char *z, int n){
208208
return EncodeHttp(z, n, 0);
209209
}
210
+
211
+/*
212
+** If input string does not contain quotes (niether ' nor ")
213
+** then return the argument itself. Otherwise return a newly allocated
214
+** copy of input with all quotes %-escaped.
215
+*/
216
+const char* escape_quotes(const char *zIn){
217
+ char *zRet, *zOut;
218
+ size_t i, n = 0;
219
+ for(i=0; zIn[i]; i++){
220
+ if( zIn[i]== '"' || zIn[i]== '\'' ) n++;
221
+ }
222
+ if( !n ) return zIn;
223
+ zRet = zOut = fossil_malloc( i + 2*n + 1 );
224
+ for(i=0; zIn[i]; i++){
225
+ if( zIn[i]=='"' ){
226
+ *(zOut++) = '%';
227
+ *(zOut++) = '2';
228
+ *(zOut++) = '2';
229
+ }else if( zIn[i]=='\'' ){
230
+ *(zOut++) = '%';
231
+ *(zOut++) = '2';
232
+ *(zOut++) = '7';
233
+ }else{
234
+ *(zOut++) = zIn[i];
235
+ }
236
+ }
237
+ *zOut = 0;
238
+ return zRet;
239
+}
210240
211241
/*
212242
** Convert a single HEX digit to an integer
213243
*/
214244
static int AsciiToHex(int c){
215245
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205 ** by this routine.
206 */
207 char *urlize(const char *z, int n){
208 return EncodeHttp(z, n, 0);
209 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
211 /*
212 ** Convert a single HEX digit to an integer
213 */
214 static int AsciiToHex(int c){
215
--- src/encode.c
+++ src/encode.c
@@ -205,10 +205,40 @@
205 ** by this routine.
206 */
207 char *urlize(const char *z, int n){
208 return EncodeHttp(z, n, 0);
209 }
210
211 /*
212 ** If input string does not contain quotes (niether ' nor ")
213 ** then return the argument itself. Otherwise return a newly allocated
214 ** copy of input with all quotes %-escaped.
215 */
216 const char* escape_quotes(const char *zIn){
217 char *zRet, *zOut;
218 size_t i, n = 0;
219 for(i=0; zIn[i]; i++){
220 if( zIn[i]== '"' || zIn[i]== '\'' ) n++;
221 }
222 if( !n ) return zIn;
223 zRet = zOut = fossil_malloc( i + 2*n + 1 );
224 for(i=0; zIn[i]; i++){
225 if( zIn[i]=='"' ){
226 *(zOut++) = '%';
227 *(zOut++) = '2';
228 *(zOut++) = '2';
229 }else if( zIn[i]=='\'' ){
230 *(zOut++) = '%';
231 *(zOut++) = '2';
232 *(zOut++) = '7';
233 }else{
234 *(zOut++) = zIn[i];
235 }
236 }
237 *zOut = 0;
238 return zRet;
239 }
240
241 /*
242 ** Convert a single HEX digit to an integer
243 */
244 static int AsciiToHex(int c){
245
+7 -3
--- src/style.c
+++ src/style.c
@@ -408,24 +408,28 @@
408408
}
409409
410410
/* Use this for the $base_href_suffix variable if it is not NULL.
411411
** If it is NULL then use g.zRelReqURI
412412
*/
413
-static char *local_zBaseHrefSuffix = 0;
413
+static const char *local_zBaseHrefSuffix = 0;
414414
415415
/*
416416
** Set the desired $base_href_suffix to something other than g.zRelReqURI
417417
*/
418418
void style_set_base_href_suffix(const char *zFormat, ...){
419
- fossil_free(local_zBaseHrefSuffix);
419
+ fossil_free( (char*)local_zBaseHrefSuffix );
420420
if( zFormat==0 ){
421421
local_zBaseHrefSuffix = 0;
422422
}else{
423
+ char *z;
423424
va_list ap;
425
+
424426
va_start(ap, zFormat);
425
- local_zBaseHrefSuffix = vmprintf(zFormat, ap);
427
+ z = vmprintf(zFormat, ap);
426428
va_end(ap);
429
+ local_zBaseHrefSuffix = escape_quotes( z );
430
+ if( local_zBaseHrefSuffix!=z ) fossil_free( z );
427431
}
428432
}
429433
430434
/*
431435
** Create a TH1 variable containing the URL for the stylesheet.
432436
--- src/style.c
+++ src/style.c
@@ -408,24 +408,28 @@
408 }
409
410 /* Use this for the $base_href_suffix variable if it is not NULL.
411 ** If it is NULL then use g.zRelReqURI
412 */
413 static char *local_zBaseHrefSuffix = 0;
414
415 /*
416 ** Set the desired $base_href_suffix to something other than g.zRelReqURI
417 */
418 void style_set_base_href_suffix(const char *zFormat, ...){
419 fossil_free(local_zBaseHrefSuffix);
420 if( zFormat==0 ){
421 local_zBaseHrefSuffix = 0;
422 }else{
 
423 va_list ap;
 
424 va_start(ap, zFormat);
425 local_zBaseHrefSuffix = vmprintf(zFormat, ap);
426 va_end(ap);
 
 
427 }
428 }
429
430 /*
431 ** Create a TH1 variable containing the URL for the stylesheet.
432
--- src/style.c
+++ src/style.c
@@ -408,24 +408,28 @@
408 }
409
410 /* Use this for the $base_href_suffix variable if it is not NULL.
411 ** If it is NULL then use g.zRelReqURI
412 */
413 static const char *local_zBaseHrefSuffix = 0;
414
415 /*
416 ** Set the desired $base_href_suffix to something other than g.zRelReqURI
417 */
418 void style_set_base_href_suffix(const char *zFormat, ...){
419 fossil_free( (char*)local_zBaseHrefSuffix );
420 if( zFormat==0 ){
421 local_zBaseHrefSuffix = 0;
422 }else{
423 char *z;
424 va_list ap;
425
426 va_start(ap, zFormat);
427 z = vmprintf(zFormat, ap);
428 va_end(ap);
429 local_zBaseHrefSuffix = escape_quotes( z );
430 if( local_zBaseHrefSuffix!=z ) fossil_free( z );
431 }
432 }
433
434 /*
435 ** Create a TH1 variable containing the URL for the stylesheet.
436

Keyboard Shortcuts

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