Fossil SCM
Amend [9919dfbbaa], again: Include an optional directory separator in buffer size calculation, guard against the unlikely (impossible?) case that a case-adjusted filename component round-tripping from UTF-8 to UTF-16 and back get longer, plus some unrelated white space fix.
Commit
49262642f421900cab3f58bf913417176410d036d0d06b19f17f6a8433d01265
Parent
163f2f599e9f917…
1 file changed
+12
-8
+12
-8
| --- src/winfile.c | ||
| +++ src/winfile.c | ||
| @@ -349,17 +349,17 @@ | ||
| 349 | 349 | const char *zBase, |
| 350 | 350 | const char *zPath |
| 351 | 351 | ){ |
| 352 | 352 | int cchBase = strlen(zBase); |
| 353 | 353 | int cchPath = strlen(zPath); |
| 354 | - int cchBuf = cchBase + cchPath + 1; | |
| 355 | - int cchRes = cchPath + 1; | |
| 354 | + int cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */ | |
| 355 | + int cchRes = cchPath + 1; /* + NULL */ | |
| 356 | 356 | char *zBuf = fossil_malloc(cchBuf); |
| 357 | 357 | char *zRes = fossil_malloc(cchRes); |
| 358 | + int ncUsed = 0; | |
| 358 | 359 | int i, j; |
| 359 | 360 | memcpy(zBuf,zBase,cchBase); |
| 360 | - cchRes = 0; | |
| 361 | 361 | if( !IS_DIRSEP(zBuf,cchBase-1) ){ |
| 362 | 362 | zBuf[cchBase++]=L'/'; |
| 363 | 363 | } |
| 364 | 364 | memcpy(zBuf+cchBase,zPath,cchPath+1); |
| 365 | 365 | i = j = cchBase; |
| @@ -371,21 +371,21 @@ | ||
| 371 | 371 | char *zComp = &zBuf[i]; |
| 372 | 372 | int cchComp; |
| 373 | 373 | char chSep; |
| 374 | 374 | int fDone; |
| 375 | 375 | if( IS_DIRSEP(zBuf,i) ){ |
| 376 | - zRes[cchRes++] = zBuf[i]; | |
| 376 | + zRes[ncUsed++] = zBuf[i]; | |
| 377 | 377 | i = j = i+1; |
| 378 | 378 | continue; |
| 379 | 379 | } |
| 380 | 380 | NEXT_DIRSEP(zBuf,j); |
| 381 | 381 | fDone = zBuf[j]==0; |
| 382 | 382 | chSep = zBuf[j]; |
| 383 | 383 | zBuf[j] = 0; /* Truncate working buffer. */ |
| 384 | 384 | wzBuf = fossil_utf8_to_path(zBuf,0); |
| 385 | 385 | hFind = FindFirstFileW(wzBuf,&fd); |
| 386 | - if( hFind!= INVALID_HANDLE_VALUE ){ | |
| 386 | + if( hFind!=INVALID_HANDLE_VALUE ){ | |
| 387 | 387 | wchar_t *wzComp = fossil_utf8_to_path(zComp,0); |
| 388 | 388 | FindClose(hFind); |
| 389 | 389 | /* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */ |
| 390 | 390 | if( win32_compare_filenames_nocase(wzComp,fd.cFileName)==0 ){ |
| 391 | 391 | zCompBuf = fossil_path_to_utf8(fd.cFileName); |
| @@ -393,21 +393,25 @@ | ||
| 393 | 393 | } |
| 394 | 394 | fossil_path_free(wzComp); |
| 395 | 395 | } |
| 396 | 396 | fossil_path_free(wzBuf); |
| 397 | 397 | cchComp = strlen(zComp); |
| 398 | - memcpy(zRes+cchRes,zComp,cchComp); | |
| 399 | - cchRes += cchComp; | |
| 398 | + if( ncUsed+cchComp+1>cchRes ){ | |
| 399 | + cchRes = ncUsed + cchComp + 32; /* While at it, add some extra space. */ | |
| 400 | + zRes = fossil_realloc(zRes,cchRes); | |
| 401 | + } | |
| 402 | + memcpy(zRes+ncUsed,zComp,cchComp); | |
| 403 | + ncUsed += cchComp; | |
| 400 | 404 | if( zCompBuf ){ |
| 401 | 405 | fossil_path_free(zCompBuf); |
| 402 | 406 | } |
| 403 | 407 | if( fDone ){ |
| 404 | - zRes[cchRes] = 0; | |
| 408 | + zRes[ncUsed] = 0; | |
| 405 | 409 | break; |
| 406 | 410 | } |
| 407 | 411 | zBuf[j] = chSep; /* Undo working buffer truncation. */ |
| 408 | 412 | i = j; |
| 409 | 413 | } |
| 410 | 414 | fossil_free(zBuf); |
| 411 | 415 | return zRes; |
| 412 | 416 | } |
| 413 | 417 | #endif /* _WIN32 -- This code is for win32 only */ |
| 414 | 418 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -349,17 +349,17 @@ | |
| 349 | const char *zBase, |
| 350 | const char *zPath |
| 351 | ){ |
| 352 | int cchBase = strlen(zBase); |
| 353 | int cchPath = strlen(zPath); |
| 354 | int cchBuf = cchBase + cchPath + 1; |
| 355 | int cchRes = cchPath + 1; |
| 356 | char *zBuf = fossil_malloc(cchBuf); |
| 357 | char *zRes = fossil_malloc(cchRes); |
| 358 | int i, j; |
| 359 | memcpy(zBuf,zBase,cchBase); |
| 360 | cchRes = 0; |
| 361 | if( !IS_DIRSEP(zBuf,cchBase-1) ){ |
| 362 | zBuf[cchBase++]=L'/'; |
| 363 | } |
| 364 | memcpy(zBuf+cchBase,zPath,cchPath+1); |
| 365 | i = j = cchBase; |
| @@ -371,21 +371,21 @@ | |
| 371 | char *zComp = &zBuf[i]; |
| 372 | int cchComp; |
| 373 | char chSep; |
| 374 | int fDone; |
| 375 | if( IS_DIRSEP(zBuf,i) ){ |
| 376 | zRes[cchRes++] = zBuf[i]; |
| 377 | i = j = i+1; |
| 378 | continue; |
| 379 | } |
| 380 | NEXT_DIRSEP(zBuf,j); |
| 381 | fDone = zBuf[j]==0; |
| 382 | chSep = zBuf[j]; |
| 383 | zBuf[j] = 0; /* Truncate working buffer. */ |
| 384 | wzBuf = fossil_utf8_to_path(zBuf,0); |
| 385 | hFind = FindFirstFileW(wzBuf,&fd); |
| 386 | if( hFind!= INVALID_HANDLE_VALUE ){ |
| 387 | wchar_t *wzComp = fossil_utf8_to_path(zComp,0); |
| 388 | FindClose(hFind); |
| 389 | /* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */ |
| 390 | if( win32_compare_filenames_nocase(wzComp,fd.cFileName)==0 ){ |
| 391 | zCompBuf = fossil_path_to_utf8(fd.cFileName); |
| @@ -393,21 +393,25 @@ | |
| 393 | } |
| 394 | fossil_path_free(wzComp); |
| 395 | } |
| 396 | fossil_path_free(wzBuf); |
| 397 | cchComp = strlen(zComp); |
| 398 | memcpy(zRes+cchRes,zComp,cchComp); |
| 399 | cchRes += cchComp; |
| 400 | if( zCompBuf ){ |
| 401 | fossil_path_free(zCompBuf); |
| 402 | } |
| 403 | if( fDone ){ |
| 404 | zRes[cchRes] = 0; |
| 405 | break; |
| 406 | } |
| 407 | zBuf[j] = chSep; /* Undo working buffer truncation. */ |
| 408 | i = j; |
| 409 | } |
| 410 | fossil_free(zBuf); |
| 411 | return zRes; |
| 412 | } |
| 413 | #endif /* _WIN32 -- This code is for win32 only */ |
| 414 |
| --- src/winfile.c | |
| +++ src/winfile.c | |
| @@ -349,17 +349,17 @@ | |
| 349 | const char *zBase, |
| 350 | const char *zPath |
| 351 | ){ |
| 352 | int cchBase = strlen(zBase); |
| 353 | int cchPath = strlen(zPath); |
| 354 | int cchBuf = cchBase + cchPath + 2; /* + NULL + optional directory slash */ |
| 355 | int cchRes = cchPath + 1; /* + NULL */ |
| 356 | char *zBuf = fossil_malloc(cchBuf); |
| 357 | char *zRes = fossil_malloc(cchRes); |
| 358 | int ncUsed = 0; |
| 359 | int i, j; |
| 360 | memcpy(zBuf,zBase,cchBase); |
| 361 | if( !IS_DIRSEP(zBuf,cchBase-1) ){ |
| 362 | zBuf[cchBase++]=L'/'; |
| 363 | } |
| 364 | memcpy(zBuf+cchBase,zPath,cchPath+1); |
| 365 | i = j = cchBase; |
| @@ -371,21 +371,21 @@ | |
| 371 | char *zComp = &zBuf[i]; |
| 372 | int cchComp; |
| 373 | char chSep; |
| 374 | int fDone; |
| 375 | if( IS_DIRSEP(zBuf,i) ){ |
| 376 | zRes[ncUsed++] = zBuf[i]; |
| 377 | i = j = i+1; |
| 378 | continue; |
| 379 | } |
| 380 | NEXT_DIRSEP(zBuf,j); |
| 381 | fDone = zBuf[j]==0; |
| 382 | chSep = zBuf[j]; |
| 383 | zBuf[j] = 0; /* Truncate working buffer. */ |
| 384 | wzBuf = fossil_utf8_to_path(zBuf,0); |
| 385 | hFind = FindFirstFileW(wzBuf,&fd); |
| 386 | if( hFind!=INVALID_HANDLE_VALUE ){ |
| 387 | wchar_t *wzComp = fossil_utf8_to_path(zComp,0); |
| 388 | FindClose(hFind); |
| 389 | /* Test fd.cFileName, not fd.cAlternateFileName (classic 8.3 format). */ |
| 390 | if( win32_compare_filenames_nocase(wzComp,fd.cFileName)==0 ){ |
| 391 | zCompBuf = fossil_path_to_utf8(fd.cFileName); |
| @@ -393,21 +393,25 @@ | |
| 393 | } |
| 394 | fossil_path_free(wzComp); |
| 395 | } |
| 396 | fossil_path_free(wzBuf); |
| 397 | cchComp = strlen(zComp); |
| 398 | if( ncUsed+cchComp+1>cchRes ){ |
| 399 | cchRes = ncUsed + cchComp + 32; /* While at it, add some extra space. */ |
| 400 | zRes = fossil_realloc(zRes,cchRes); |
| 401 | } |
| 402 | memcpy(zRes+ncUsed,zComp,cchComp); |
| 403 | ncUsed += cchComp; |
| 404 | if( zCompBuf ){ |
| 405 | fossil_path_free(zCompBuf); |
| 406 | } |
| 407 | if( fDone ){ |
| 408 | zRes[ncUsed] = 0; |
| 409 | break; |
| 410 | } |
| 411 | zBuf[j] = chSep; /* Undo working buffer truncation. */ |
| 412 | i = j; |
| 413 | } |
| 414 | fossil_free(zBuf); |
| 415 | return zRes; |
| 416 | } |
| 417 | #endif /* _WIN32 -- This code is for win32 only */ |
| 418 |