Fossil SCM

Fix build (previous cherry-pick was not complete) (cherry-pick): For temporary filename paths on Windows, changes all backslash characters into forward slashes, so that the new enhanced-security shell escape mechanism from check-in [3b191c98] can use those temporary filenames.

jan.nijtmans 2017-08-23 17:28 UTC branch-2.3
Commit dbda6e2a5dcd94de52afedeebf6e53d94ee095fc6052b2aa0469478e14063f09
3 files changed +44 -18 +8 -11 +5
+44 -18
--- src/blob.c
+++ src/blob.c
@@ -1169,28 +1169,54 @@
11691169
}
11701170
}
11711171
}
11721172
11731173
/*
1174
-** Shell-escape the given string. Append the result to a blob.
1175
-*/
1176
-void shell_escape(Blob *pBlob, const char *zIn){
1177
- int n = blob_size(pBlob);
1178
- int k = strlen(zIn);
1179
- int i, c;
1180
- char *z;
1181
- for(i=0; (c = zIn[i])!=0; i++){
1182
- if( fossil_isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){
1183
- blob_appendf(pBlob, "\"%s\"", zIn);
1184
- z = blob_buffer(pBlob);
1185
- for(i=n+1; i<=n+k; i++){
1186
- if( z[i]=='"' ) z[i] = '_';
1187
- }
1188
- return;
1189
- }
1190
- }
1191
- blob_append(pBlob, zIn, -1);
1174
+** pBlob is a shell command under construction. This routine safely
1175
+** appends argument zIn.
1176
+**
1177
+** The argument is escaped if it contains white space or other characters
1178
+** that need to be escaped for the shell. If zIn contains characters
1179
+** that cannot be safely escaped, then throw a fatal error.
1180
+**
1181
+** The argument is expected to a filename of some kinds. As shell commands
1182
+** commonly have command-line options that begin with "-" and since we
1183
+** do not want an attacker to be able to invoke these switches using
1184
+** filenames that begin with "-", if zIn begins with "-", prepend
1185
+** an additional "./".
1186
+*/
1187
+void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1188
+ int i;
1189
+ char c;
1190
+ int needEscape = 0;
1191
+ int n = blob_size(pBlob);
1192
+ char *z = blob_buffer(pBlob);
1193
+#if defined(_WIN32)
1194
+ const char cQuote = '"'; /* Use "..." quoting on windows */
1195
+#else
1196
+ const char cQuote = '\''; /* Use '...' quoting on unix */
1197
+#endif
1198
+
1199
+ for(i=0; (c = zIn[i])!=0; i++){
1200
+ if( c==cQuote || c=='\\' || c<' ' || c==';' || c=='*' || c=='?' || c=='[') {
1201
+ Blob bad;
1202
+ blob_token(pBlob, &bad);
1203
+ fossil_fatal("the [%s] argument to the \"%s\" command contains "
1204
+ "a character (ascii 0x%02x) that is a security risk",
1205
+ zIn, blob_str(&bad), c);
1206
+ }
1207
+ if( !needEscape && !fossil_isalnum(c) && c!='/' && c!='.' && c!='_' ){
1208
+ needEscape = 1;
1209
+ }
1210
+ }
1211
+ if( n>0 && !fossil_isspace(z[n-1]) ){
1212
+ blob_append(pBlob, " ", 1);
1213
+ }
1214
+ if( needEscape ) blob_append(pBlob, &cQuote, 1);
1215
+ if( zIn[0]=='-' ) blob_append(pBlob, "./", 2);
1216
+ blob_append(pBlob, zIn, -1);
1217
+ if( needEscape ) blob_append(pBlob, &cQuote, 1);
11921218
}
11931219
11941220
/*
11951221
** A read(2)-like impl for the Blob class. Reads (copies) up to nLen
11961222
** bytes from pIn, starting at position pIn->iCursor, and copies them
11971223
--- src/blob.c
+++ src/blob.c
@@ -1169,28 +1169,54 @@
1169 }
1170 }
1171 }
1172
1173 /*
1174 ** Shell-escape the given string. Append the result to a blob.
1175 */
1176 void shell_escape(Blob *pBlob, const char *zIn){
1177 int n = blob_size(pBlob);
1178 int k = strlen(zIn);
1179 int i, c;
1180 char *z;
1181 for(i=0; (c = zIn[i])!=0; i++){
1182 if( fossil_isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){
1183 blob_appendf(pBlob, "\"%s\"", zIn);
1184 z = blob_buffer(pBlob);
1185 for(i=n+1; i<=n+k; i++){
1186 if( z[i]=='"' ) z[i] = '_';
1187 }
1188 return;
1189 }
1190 }
1191 blob_append(pBlob, zIn, -1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1192 }
1193
1194 /*
1195 ** A read(2)-like impl for the Blob class. Reads (copies) up to nLen
1196 ** bytes from pIn, starting at position pIn->iCursor, and copies them
1197
--- src/blob.c
+++ src/blob.c
@@ -1169,28 +1169,54 @@
1169 }
1170 }
1171 }
1172
1173 /*
1174 ** pBlob is a shell command under construction. This routine safely
1175 ** appends argument zIn.
1176 **
1177 ** The argument is escaped if it contains white space or other characters
1178 ** that need to be escaped for the shell. If zIn contains characters
1179 ** that cannot be safely escaped, then throw a fatal error.
1180 **
1181 ** The argument is expected to a filename of some kinds. As shell commands
1182 ** commonly have command-line options that begin with "-" and since we
1183 ** do not want an attacker to be able to invoke these switches using
1184 ** filenames that begin with "-", if zIn begins with "-", prepend
1185 ** an additional "./".
1186 */
1187 void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1188 int i;
1189 char c;
1190 int needEscape = 0;
1191 int n = blob_size(pBlob);
1192 char *z = blob_buffer(pBlob);
1193 #if defined(_WIN32)
1194 const char cQuote = '"'; /* Use "..." quoting on windows */
1195 #else
1196 const char cQuote = '\''; /* Use '...' quoting on unix */
1197 #endif
1198
1199 for(i=0; (c = zIn[i])!=0; i++){
1200 if( c==cQuote || c=='\\' || c<' ' || c==';' || c=='*' || c=='?' || c=='[') {
1201 Blob bad;
1202 blob_token(pBlob, &bad);
1203 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1204 "a character (ascii 0x%02x) that is a security risk",
1205 zIn, blob_str(&bad), c);
1206 }
1207 if( !needEscape && !fossil_isalnum(c) && c!='/' && c!='.' && c!='_' ){
1208 needEscape = 1;
1209 }
1210 }
1211 if( n>0 && !fossil_isspace(z[n-1]) ){
1212 blob_append(pBlob, " ", 1);
1213 }
1214 if( needEscape ) blob_append(pBlob, &cQuote, 1);
1215 if( zIn[0]=='-' ) blob_append(pBlob, "./", 2);
1216 blob_append(pBlob, zIn, -1);
1217 if( needEscape ) blob_append(pBlob, &cQuote, 1);
1218 }
1219
1220 /*
1221 ** A read(2)-like impl for the Blob class. Reads (copies) up to nLen
1222 ** bytes from pIn, starting at position pIn->iCursor, and copies them
1223
+8 -11
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -263,19 +263,17 @@
263263
}while( file_access(blob_str(&nameFile1),F_OK)==0 );
264264
blob_write_to_file(pFile1, blob_str(&nameFile1));
265265
266266
/* Construct the external diff command */
267267
blob_zero(&cmd);
268
- blob_appendf(&cmd, "%s ", zDiffCmd);
268
+ blob_append(&cmd, zDiffCmd, -1);
269269
if( fSwapDiff ){
270
- shell_escape(&cmd, zFile2);
271
- blob_append(&cmd, " ", 1);
272
- shell_escape(&cmd, blob_str(&nameFile1));
270
+ blob_append_escaped_arg(&cmd, zFile2);
271
+ blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
273272
}else{
274
- shell_escape(&cmd, blob_str(&nameFile1));
275
- blob_append(&cmd, " ", 1);
276
- shell_escape(&cmd, zFile2);
273
+ blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
274
+ blob_append_escaped_arg(&cmd, zFile2);
277275
}
278276
279277
/* Run the external diff command */
280278
fossil_system(blob_str(&cmd));
281279
@@ -360,14 +358,13 @@
360358
blob_write_to_file(pFile1, blob_str(&temp1));
361359
blob_write_to_file(pFile2, blob_str(&temp2));
362360
363361
/* Construct the external diff command */
364362
blob_zero(&cmd);
365
- blob_appendf(&cmd, "%s ", zDiffCmd);
366
- shell_escape(&cmd, blob_str(&temp1));
367
- blob_append(&cmd, " ", 1);
368
- shell_escape(&cmd, blob_str(&temp2));
363
+ blob_append(&cmd, zDiffCmd, -1);
364
+ blob_append_escaped_arg(&cmd, blob_str(&temp1));
365
+ blob_append_escaped_arg(&cmd, blob_str(&temp2));
369366
370367
/* Run the external diff command */
371368
fossil_system(blob_str(&cmd));
372369
373370
/* Delete the temporary file and clean up memory used */
374371
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -263,19 +263,17 @@
263 }while( file_access(blob_str(&nameFile1),F_OK)==0 );
264 blob_write_to_file(pFile1, blob_str(&nameFile1));
265
266 /* Construct the external diff command */
267 blob_zero(&cmd);
268 blob_appendf(&cmd, "%s ", zDiffCmd);
269 if( fSwapDiff ){
270 shell_escape(&cmd, zFile2);
271 blob_append(&cmd, " ", 1);
272 shell_escape(&cmd, blob_str(&nameFile1));
273 }else{
274 shell_escape(&cmd, blob_str(&nameFile1));
275 blob_append(&cmd, " ", 1);
276 shell_escape(&cmd, zFile2);
277 }
278
279 /* Run the external diff command */
280 fossil_system(blob_str(&cmd));
281
@@ -360,14 +358,13 @@
360 blob_write_to_file(pFile1, blob_str(&temp1));
361 blob_write_to_file(pFile2, blob_str(&temp2));
362
363 /* Construct the external diff command */
364 blob_zero(&cmd);
365 blob_appendf(&cmd, "%s ", zDiffCmd);
366 shell_escape(&cmd, blob_str(&temp1));
367 blob_append(&cmd, " ", 1);
368 shell_escape(&cmd, blob_str(&temp2));
369
370 /* Run the external diff command */
371 fossil_system(blob_str(&cmd));
372
373 /* Delete the temporary file and clean up memory used */
374
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -263,19 +263,17 @@
263 }while( file_access(blob_str(&nameFile1),F_OK)==0 );
264 blob_write_to_file(pFile1, blob_str(&nameFile1));
265
266 /* Construct the external diff command */
267 blob_zero(&cmd);
268 blob_append(&cmd, zDiffCmd, -1);
269 if( fSwapDiff ){
270 blob_append_escaped_arg(&cmd, zFile2);
271 blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
 
272 }else{
273 blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
274 blob_append_escaped_arg(&cmd, zFile2);
 
275 }
276
277 /* Run the external diff command */
278 fossil_system(blob_str(&cmd));
279
@@ -360,14 +358,13 @@
358 blob_write_to_file(pFile1, blob_str(&temp1));
359 blob_write_to_file(pFile2, blob_str(&temp2));
360
361 /* Construct the external diff command */
362 blob_zero(&cmd);
363 blob_append(&cmd, zDiffCmd, -1);
364 blob_append_escaped_arg(&cmd, blob_str(&temp1));
365 blob_append_escaped_arg(&cmd, blob_str(&temp2));
 
366
367 /* Run the external diff command */
368 fossil_system(blob_str(&cmd));
369
370 /* Delete the temporary file and clean up memory used */
371
+5
--- src/file.c
+++ src/file.c
@@ -1388,10 +1388,11 @@
13881388
0, /* GetTempPath */
13891389
0, /* TEMP */
13901390
0, /* TMP */
13911391
".",
13921392
};
1393
+ char *z;
13931394
#else
13941395
static const char *azDirs[] = {
13951396
0, /* TMPDIR */
13961397
"/var/tmp",
13971398
"/usr/tmp",
@@ -1442,10 +1443,14 @@
14421443
14431444
#if defined(_WIN32)
14441445
fossil_path_free((char *)azDirs[0]);
14451446
fossil_path_free((char *)azDirs[1]);
14461447
fossil_path_free((char *)azDirs[2]);
1448
+ /* Change all \ characters in the windows path into / so that they can
1449
+ ** be safely passed to a subcommand, such as by gdiff */
1450
+ z = blob_buffer(pBuf);
1451
+ for(i=0; z[i]; i++) if( z[i]=='\\' ) z[i] = '/';
14471452
#else
14481453
fossil_path_free((char *)azDirs[0]);
14491454
#endif
14501455
}
14511456
14521457
--- src/file.c
+++ src/file.c
@@ -1388,10 +1388,11 @@
1388 0, /* GetTempPath */
1389 0, /* TEMP */
1390 0, /* TMP */
1391 ".",
1392 };
 
1393 #else
1394 static const char *azDirs[] = {
1395 0, /* TMPDIR */
1396 "/var/tmp",
1397 "/usr/tmp",
@@ -1442,10 +1443,14 @@
1442
1443 #if defined(_WIN32)
1444 fossil_path_free((char *)azDirs[0]);
1445 fossil_path_free((char *)azDirs[1]);
1446 fossil_path_free((char *)azDirs[2]);
 
 
 
 
1447 #else
1448 fossil_path_free((char *)azDirs[0]);
1449 #endif
1450 }
1451
1452
--- src/file.c
+++ src/file.c
@@ -1388,10 +1388,11 @@
1388 0, /* GetTempPath */
1389 0, /* TEMP */
1390 0, /* TMP */
1391 ".",
1392 };
1393 char *z;
1394 #else
1395 static const char *azDirs[] = {
1396 0, /* TMPDIR */
1397 "/var/tmp",
1398 "/usr/tmp",
@@ -1442,10 +1443,14 @@
1443
1444 #if defined(_WIN32)
1445 fossil_path_free((char *)azDirs[0]);
1446 fossil_path_free((char *)azDirs[1]);
1447 fossil_path_free((char *)azDirs[2]);
1448 /* Change all \ characters in the windows path into / so that they can
1449 ** be safely passed to a subcommand, such as by gdiff */
1450 z = blob_buffer(pBuf);
1451 for(i=0; z[i]; i++) if( z[i]=='\\' ) z[i] = '/';
1452 #else
1453 fossil_path_free((char *)azDirs[0]);
1454 #endif
1455 }
1456
1457

Keyboard Shortcuts

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