@@ -418,46 +418,57 @@ size_t git_win32_path_trim_end(wchar_t *str, size_t len)
418418 */
419419size_t git_win32_path_remove_namespace (wchar_t * str , size_t len )
420420{
421- static const wchar_t dosdevices_prefix [] = L"\\\?\?\\" ;
422- static const wchar_t nt_prefix [] = L"\\\\?\\" ;
423- static const wchar_t unc_prefix [] = L"UNC\\" ;
424- static const wchar_t unc_canonicalized_prefix [] = L"\\\\" ;
421+ static const wchar_t dosdevices_namespace [] = L"\\\?\?\\" ;
422+ static const wchar_t nt_namespace [] = L"\\\\?\\" ;
423+ static const wchar_t unc_namespace_remainder [] = L"UNC\\" ;
424+ static const wchar_t unc_prefix [] = L"\\\\" ;
425425
426- size_t to_advance = 0 ;
426+ const wchar_t * prefix = NULL , * remainder = NULL ;
427+ size_t prefix_len = 0 , remainder_len = 0 ;
427428
428429 /* "\??\" -- DOS Devices prefix */
429- if (len >= CONST_STRLEN (dosdevices_prefix ) &&
430- !wcsncmp (str , dosdevices_prefix , CONST_STRLEN (dosdevices_prefix ))) {
431- to_advance += CONST_STRLEN (dosdevices_prefix );
432- len -= CONST_STRLEN (dosdevices_prefix );
430+ if (len >= CONST_STRLEN (dosdevices_namespace ) &&
431+ !wcsncmp (str , dosdevices_namespace , CONST_STRLEN (dosdevices_namespace ))) {
432+ remainder = str + CONST_STRLEN (dosdevices_namespace );
433+ remainder_len = len - CONST_STRLEN (dosdevices_namespace );
433434 }
434435 /* "\\?\" -- NT namespace prefix */
435- else if (len >= CONST_STRLEN (nt_prefix ) &&
436- !wcsncmp (str , nt_prefix , CONST_STRLEN (nt_prefix ))) {
437- to_advance += CONST_STRLEN (nt_prefix );
438- len -= CONST_STRLEN (nt_prefix );
436+ else if (len >= CONST_STRLEN (nt_namespace ) &&
437+ !wcsncmp (str , nt_namespace , CONST_STRLEN (nt_namespace ))) {
438+ remainder = str + CONST_STRLEN (nt_namespace );
439+ remainder_len = len - CONST_STRLEN (nt_namespace );
439440 }
440441
441442 /* "\??\UNC\", "\\?\UNC\" -- UNC prefix */
442- if (to_advance && len >= CONST_STRLEN (unc_prefix ) &&
443- !wcsncmp (str + to_advance , unc_prefix , CONST_STRLEN (unc_prefix ))) {
443+ if (remainder_len >= CONST_STRLEN (unc_namespace_remainder ) &&
444+ !wcsncmp (remainder , unc_namespace_remainder , CONST_STRLEN (unc_namespace_remainder ))) {
444445
445446 /*
446447 * The proper Win32 path for a UNC share has "\\" at beginning of it
447- * and looks like "\\server\share\<folderStructure>".
448- * So, remove the UNC prefix, but leave room for a "\\"
448+ * and looks like "\\server\share\<folderStructure>". So remove the
449+ * UNC namespace and add a prefix of "\\" in its place.
449450 */
450- to_advance += ( CONST_STRLEN (unc_prefix ) - CONST_STRLEN ( unc_canonicalized_prefix ) );
451- len -= ( CONST_STRLEN (unc_prefix ) - CONST_STRLEN ( unc_canonicalized_prefix ) );
451+ remainder += CONST_STRLEN (unc_namespace_remainder );
452+ remainder_len -= CONST_STRLEN (unc_namespace_remainder );
452453
453- /**
454- * Place a "\\" in the string so the result is "\\server\\share\<folderStructure>"
455- */
456- memmove (str + to_advance , unc_canonicalized_prefix , CONST_STRLEN (unc_canonicalized_prefix ) * sizeof (wchar_t ));
454+ prefix = unc_prefix ;
455+ prefix_len = CONST_STRLEN (unc_prefix );
457456 }
458457
459- if (to_advance ) {
460- memmove (str , str + to_advance , len * sizeof (wchar_t ));
458+ if (remainder ) {
459+ /*
460+ * Sanity check that the new string isn't longer than the old one.
461+ * (This could only happen due to programmer error introducing a
462+ * prefix longer than the namespace it replaces.)
463+ */
464+ assert (len >= remainder_len + prefix_len );
465+
466+ if (prefix )
467+ memmove (str , prefix , prefix_len * sizeof (wchar_t ));
468+
469+ memmove (str + prefix_len , remainder , remainder_len * sizeof (wchar_t ));
470+
471+ len = remainder_len + prefix_len ;
461472 str [len ] = L'\0' ;
462473 }
463474
0 commit comments