mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-11-04 08:48:25 +00:00 
			
		
		
		
	Fix diff crash when last item is untracked dir
When the last item in a diff was an untracked directory that only contained ignored items, the loop to scan the contents would run off the end of the iterator and dereference a NULL pointer. This includes a test that reproduces the problem and a fix.
This commit is contained in:
		
							parent
							
								
									f0ab73720a
								
							
						
					
					
						commit
						79ef3be449
					
				@ -747,7 +747,8 @@ static int diff_scan_inside_untracked_dir(
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* look for actual untracked file */
 | 
			
		||||
	while (!diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
 | 
			
		||||
	while (info->nitem != NULL &&
 | 
			
		||||
		   !diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
 | 
			
		||||
		is_ignored = git_iterator_current_is_ignored(info->new_iter);
 | 
			
		||||
 | 
			
		||||
		/* need to recurse into non-ignored directories */
 | 
			
		||||
@ -769,7 +770,8 @@ static int diff_scan_inside_untracked_dir(
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* finish off scan */
 | 
			
		||||
	while (!diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
 | 
			
		||||
	while (info->nitem != NULL &&
 | 
			
		||||
		   !diff->pfxcomp(info->nitem->path, git_buf_cstr(&base))) {
 | 
			
		||||
		if ((error = git_iterator_advance(&info->nitem, info->new_iter)) < 0)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1220,3 +1220,28 @@ void test_diff_workdir__untracked_directory_scenarios(void)
 | 
			
		||||
 | 
			
		||||
	git_diff_list_free(diff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void test_diff_workdir__untracked_directory_comes_last(void)
 | 
			
		||||
{
 | 
			
		||||
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
 | 
			
		||||
	git_diff_list *diff = NULL;
 | 
			
		||||
 | 
			
		||||
	g_repo = cl_git_sandbox_init("renames");
 | 
			
		||||
 | 
			
		||||
	cl_git_mkfile("renames/.gitignore", "*.ign\n");
 | 
			
		||||
	cl_git_pass(p_mkdir("renames/zzz_untracked", 0777));
 | 
			
		||||
	cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please");
 | 
			
		||||
	cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really");
 | 
			
		||||
	cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now");
 | 
			
		||||
 | 
			
		||||
	opts.context_lines = 3;
 | 
			
		||||
	opts.interhunk_lines = 1;
 | 
			
		||||
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
 | 
			
		||||
 | 
			
		||||
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
 | 
			
		||||
 | 
			
		||||
	cl_assert(diff != NULL);
 | 
			
		||||
 | 
			
		||||
	git_diff_list_free(diff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user