git: protect against unbalanced calls to {save,restore}_env()
We made sure that save_env_before_alias() does not skip saving the environment when asked to (which led to use-after-free of orig_cwd in restore_env() in the buggy version) with the previous step. Protect against future breakage where somebody adds new callers of these functions in an unbalanced fashion. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		
							
								
								
									
										7
									
								
								git.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								git.c
									
									
									
									
									
								
							@ -26,11 +26,15 @@ static const char *env_names[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
static char *orig_env[4];
 | 
					static char *orig_env[4];
 | 
				
			||||||
static int saved_env_before_alias;
 | 
					static int saved_env_before_alias;
 | 
				
			||||||
 | 
					static int save_restore_env_balance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void save_env_before_alias(void)
 | 
					static void save_env_before_alias(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	saved_env_before_alias = 1;
 | 
						saved_env_before_alias = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(save_restore_env_balance == 0);
 | 
				
			||||||
 | 
						save_restore_env_balance = 1;
 | 
				
			||||||
	orig_cwd = xgetcwd();
 | 
						orig_cwd = xgetcwd();
 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(env_names); i++) {
 | 
						for (i = 0; i < ARRAY_SIZE(env_names); i++) {
 | 
				
			||||||
		orig_env[i] = getenv(env_names[i]);
 | 
							orig_env[i] = getenv(env_names[i]);
 | 
				
			||||||
@ -42,6 +46,9 @@ static void save_env_before_alias(void)
 | 
				
			|||||||
static void restore_env(int external_alias)
 | 
					static void restore_env(int external_alias)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(save_restore_env_balance == 1);
 | 
				
			||||||
 | 
						save_restore_env_balance = 0;
 | 
				
			||||||
	if (!external_alias && orig_cwd && chdir(orig_cwd))
 | 
						if (!external_alias && orig_cwd && chdir(orig_cwd))
 | 
				
			||||||
		die_errno("could not move to %s", orig_cwd);
 | 
							die_errno("could not move to %s", orig_cwd);
 | 
				
			||||||
	free(orig_cwd);
 | 
						free(orig_cwd);
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user