mirror of
				git://git.code.sf.net/p/cdesktopenv/code
				synced 2025-03-09 15:50:02 +00:00 
			
		
		
		
	Fix file descriptor leaks in the hist builtin (#336)
				
					
				
			This commit fixes two file descriptor leaks in the hist built-in.
The bugfix for the first file descriptor leak was backported from
ksh2020. See:
https://github.com/att/ast/issues/872
73bd61b5
Reproducer:
  $ echo no
  $ hist -s no=yes
The second file descriptor leak occurs after a substitution error
in the hist built-in (this leak wasn't fixed in ksh2020).
Reproducer:
  $ echo no
  $ ls /proc/$$/fd
  $ hist -s no=yes
  $ hist -s no=yes
  $ ls /proc/$$/fd
src/cmd/ksh93/bltins/hist.c:
- Close leftover file descriptors when an error occurs and after
  'hist -s' runs a command.
src/cmd/ksh93/tests/builtins.sh:
- Add two regression tests for both of the file descriptor leaks.
			
			
This commit is contained in:
		
							parent
							
								
									7ea95b7df3
								
							
						
					
					
						commit
						b40155fae8
					
				
					 3 changed files with 36 additions and 2 deletions
				
			
		
							
								
								
									
										3
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								NEWS
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -9,6 +9,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
 | 
			
		|||
  special floating point constants Inf and NaN so that $((inf)) and $((nan))
 | 
			
		||||
  refer to the variables by those names as the standard requires. (BUG_ARITHNAN)
 | 
			
		||||
 | 
			
		||||
- Fixed two file descriptor leaks in the hist builtin that occurred when
 | 
			
		||||
  the -s flag ran a command or encountered an error.
 | 
			
		||||
 | 
			
		||||
2021-11-14:
 | 
			
		||||
 | 
			
		||||
- Fixed: ksh crashed after unsetting .sh.match and then matching a pattern.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -264,18 +264,23 @@ int	b_hist(int argc,char *argv[], Shbltin_t *context)
 | 
			
		|||
	sh_onstate(SH_HISTORY);
 | 
			
		||||
	sh_onstate(SH_VERBOSE);	/* echo lines as read */
 | 
			
		||||
	if(replace)
 | 
			
		||||
	{
 | 
			
		||||
		hist_subst(error_info.id,fdo,replace);
 | 
			
		||||
		sh_close(fdo);
 | 
			
		||||
	}
 | 
			
		||||
	else if(error_info.errors == 0)
 | 
			
		||||
	{
 | 
			
		||||
		char buff[IOBSIZE+1];
 | 
			
		||||
		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
 | 
			
		||||
		Sfio_t *iop;
 | 
			
		||||
		/* read in and run the command */
 | 
			
		||||
		if(shp->hist_depth++ > HIST_RECURSE)
 | 
			
		||||
		{
 | 
			
		||||
			sh_close(fdo);
 | 
			
		||||
			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
 | 
			
		||||
			UNREACHABLE();
 | 
			
		||||
		}
 | 
			
		||||
		sh_eval(iop,1);
 | 
			
		||||
		iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
 | 
			
		||||
		sh_eval(iop,1); /* this will close fdo */
 | 
			
		||||
		shp->hist_depth--;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -313,6 +318,7 @@ static void hist_subst(const char *command,int fd,char *replace)
 | 
			
		|||
	*newp++ =  0;
 | 
			
		||||
	if((sp=sh_substitute(string,replace,newp))==0)
 | 
			
		||||
	{
 | 
			
		||||
		sh_close(fd);
 | 
			
		||||
		errormsg(SH_DICT,ERROR_exit(1),e_subst,command);
 | 
			
		||||
		UNREACHABLE();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1273,5 +1273,30 @@ got=$(	readonly v=foo
 | 
			
		|||
[[ $got == "$exp" ]] || err_exit "prefixing special builtin with 'command' does not stop it from exiting the shell on error" \
 | 
			
		||||
	"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
 | 
			
		||||
 | 
			
		||||
# ======
 | 
			
		||||
# https://github.com/att/ast/issues/872
 | 
			
		||||
hist_leak=$tmp/hist_leak.sh
 | 
			
		||||
print 'ulimit -n 15' > "$hist_leak"
 | 
			
		||||
for ((i=0; i!=11; i++)) do
 | 
			
		||||
	print 'true foo\nhist -s foo=bar 2> /dev/null' >> "$hist_leak"
 | 
			
		||||
done
 | 
			
		||||
print 'print OK' >> "$hist_leak"
 | 
			
		||||
exp="OK"
 | 
			
		||||
got="$($SHELL -i "$hist_leak" 2>&1)"
 | 
			
		||||
[[ $exp == "$got" ]] || err_exit "file descriptor leak in hist builtin" \
 | 
			
		||||
	"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
 | 
			
		||||
 | 
			
		||||
# File descriptor leak after hist builtin substitution error
 | 
			
		||||
hist_error_leak=$tmp/hist_error_leak.sh
 | 
			
		||||
print 'ulimit -n 15' > "$hist_error_leak"
 | 
			
		||||
for ((i=0; i!=11; i++)) do
 | 
			
		||||
	print 'hist -s no=yes 2> /dev/null' >> "$hist_error_leak"
 | 
			
		||||
done
 | 
			
		||||
print 'print OK' >> "$hist_error_leak"
 | 
			
		||||
exp="OK"
 | 
			
		||||
got="$($SHELL -i "$hist_error_leak" 2>&1)"
 | 
			
		||||
[[ $exp == "$got" ]] || err_exit "file descriptor leak after substitution error in hist builtin" \
 | 
			
		||||
	"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
 | 
			
		||||
 | 
			
		||||
# ======
 | 
			
		||||
exit $((Errors<125?Errors:125))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue