On Wed, Dec 24, 2014 at 4:43 AM, Eric Sunshine <sunshine@xxxxxxxxxxxxxx> wrote: > checkout-index --temp only properly prints relative paths which are > descendants of the current directory. Paths in ancestor or sibling > directories (or their children) are often printed in mangled form. For > example: > > mkdir a bbb && > >file && > >bbb/file && > git update-index --add file bbb/file && > cd a && > git checkout-index --temp ../file ../bbb/file > > prints: > > .merge_file_ooblek le > .merge_file_igloo0 b/file > > rather than the correct: > > .merge_file_ooblek ../file > .merge_file_igloo0 ../bbb/file > > Internally, given the above example, checkout-index prefixes each input > argument with the name of the current directory ("a/", in this case), > and then assumes that it can simply skip forward by strlen("a/") bytes > to recover the original name. This works for files in the current > directory or its descendants, but fails for files in ancestors or > siblings (or their children) due to path normalization. > > For instance, given "../file", "a/" is appended, giving "a/../file". s/appended/prepended/ > Path normalization folds out "a/../", resulting in "file". Attempting > to recover the original name by skipping strlen("a/") bytes gives the > incorrect "le" rather than the desired "../file". > > Fix this by taking advantage of write_name_quoted_relative() to recover > the original name properly, rather than assuming that it can be > recovered by skipping strlen(prefix) bytes. > > As a bonus, this also fixes a bug in which checkout-index --temp > accessed and printed memory beyond the end-of-string. For instance, > within a subdirectory named "subdirectory", and given argument > "../file", prefixing would give "subdirectory/../file", which would > become "file" after normalization. checkout-index would then attempt to > recover the original name by skipping strlen("subdirectory/") bytes of > "file", which placed it well beyond end-of-string. Despite this error, > it often appeared to give the correct result, but only due to an > accident of implementation which left an apparently correct copy of the > path in memory following the normalized value. In particular, handed > "subdirectory/../file", in-place processing by normalize_path_copy_len() > resulted in "file\0rectory/../file". When checkout-index skipped > strlen("subdirectory/") bytes, it ended up back at "../file" and thus > appeared to give the correct answer, despite being past end-of-string. > > Reported-by: Russ Cox <rsc@xxxxxxxxxx> > Signed-off-by: Eric Sunshine <sunshine@xxxxxxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html