mirror of
				git://git.code.sf.net/p/cdesktopenv/code
				synced 2025-03-09 15:50:02 +00:00 
			
		
		
		
	Fix octal number arguments in printf integer arithmetic
Bug 1: POSIX requires numbers used as arguments for all the %d, %u... in printf to be interpreted as in the C language, so printf '%d\n' 010 should output 8 when the posix option is on. However, it outputs 10. This bug was introduced as a side effect of a change introduced in the 2012-02-07 version of ksh 93u+m, which caused the recognition of leading-zero numbers as octal in arithmetic expressions to be disabled outside ((...)) and $((...)). However, POSIX requires leading-zero octal numbers to be recognised for printf, too. The change in question introduced a sh.arith flag that is set while we're processing a POSIX arithmetic expression, i.e., one that recognises leading-zero octal numbers. Bug 2: Said flag is not reset in a command substitution used within an arithmetic expression. A command substitution should be a completely new context, so the following should both output 10: $ ksh -c 'integer x; x=010; echo $x' 10 # ok; it's outside ((…)) so octals are not recognised $ ksh -c 'echo $(( $(integer x; x=010; echo $x) ))' 8 # bad; $(comsub) should create new non-((…)) context src/cmd/ksh93/bltins/print.c: extend(): - For the u, d, i, o, x, and X conversion modifiers, set the POSIX arithmetic context flag before calling sh_strnum() to convert the argument. This fixes bug 1. src/cmd/ksh93/sh/subshell.c: sh_subshell(): - When invoking a command substitution, save and unset the POSIX arithmetic context flag. Restore it at the end. This fixes bug 2. Reported-by: @stephane-chazelas Resolves: https://github.com/ksh93/ksh/issues/326
This commit is contained in:
		
							parent
							
								
									44bdb3fbfc
								
							
						
					
					
						commit
						7b5b0a5d54
					
				
					 8 changed files with 50 additions and 3 deletions
				
			
		
							
								
								
									
										12
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								NEWS
									
										
									
									
									
								
							| 
						 | 
					@ -3,6 +3,18 @@ For full details, see the git log at: https://github.com/ksh93/ksh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Any uppercase BUG_* names are modernish shell bug IDs.
 | 
					Any uppercase BUG_* names are modernish shell bug IDs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2021-09-13:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fixed a bug introduced in 93u+ 2012-02-07 that caused the 'printf' builtin
 | 
				
			||||||
 | 
					  (and its 'print -f' equivalent) to fail to recognise integer arguments with a
 | 
				
			||||||
 | 
					  leading zero as octal numbers. For example, 'printf "%d\n" 010' now once
 | 
				
			||||||
 | 
					  again outputs '8' instead of '10'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Disable the POSIX arithmetic context while running a command substitution
 | 
				
			||||||
 | 
					  invoked from within an arithmetic expression. This fixes a bug that caused
 | 
				
			||||||
 | 
					  integer arguments with a leading zero to be incorrectly interpreted as octal
 | 
				
			||||||
 | 
					  numbers in non-POSIX arithmetic contexts within such command substitutions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2021-09-12:
 | 
					2021-09-12:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- When invoking a script without an interpreter/hashbang path on Linux and
 | 
					- When invoking a script without an interpreter/hashbang path on Linux and
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,6 +151,11 @@ For more details, see the NEWS file and for complete details, see the git log.
 | 
				
			||||||
	correctly negates another '!', e.g., [[ ! ! 1 -eq 1 ]] now returns
 | 
						correctly negates another '!', e.g., [[ ! ! 1 -eq 1 ]] now returns
 | 
				
			||||||
	0/true. Note that this has always been the case for 'test'/'['.
 | 
						0/true. Note that this has always been the case for 'test'/'['.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					28.	In the 'printf' builtin (and the 'print -f' equivalent), numeric
 | 
				
			||||||
 | 
						arguments with a leading zero are now once again recognized as octal
 | 
				
			||||||
 | 
						numbers as in ksh93 versions before 2012-02-07, and as POSIX requires.
 | 
				
			||||||
 | 
						For example, 'printf "%d\n" 010' now once again outputs '8'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
____________________________________________________________________________
 | 
					____________________________________________________________________________
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		KSH-93 VS. KSH-88
 | 
							KSH-93 VS. KSH-88
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -882,7 +882,9 @@ static int extend(Sfio_t* sp, void* v, Sffmt_t* fe)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
 | 
									shp->inarith = 1;	/* POSIX compliance: recognize octal constants, e.g. printf '%d\n' 010 */
 | 
				
			||||||
				d = sh_strnum(argp,&lastchar,0);
 | 
									d = sh_strnum(argp,&lastchar,0);
 | 
				
			||||||
 | 
									shp->inarith = 0;
 | 
				
			||||||
				if(d<longmin)
 | 
									if(d<longmin)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
 | 
										errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1193,7 +1193,7 @@ const char sh_optprint[] =
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char sh_optprintf[] =
 | 
					const char sh_optprintf[] =
 | 
				
			||||||
"[-1c?\n@(#)$Id: printf (ksh 93u+m) 2020-08-10 $\n]"
 | 
					"[-1c?\n@(#)$Id: printf (ksh 93u+m) 2021-09-13 $\n]"
 | 
				
			||||||
"[--catalog?" SH_DICT "]"
 | 
					"[--catalog?" SH_DICT "]"
 | 
				
			||||||
"[+NAME?printf - write formatted output]"
 | 
					"[+NAME?printf - write formatted output]"
 | 
				
			||||||
"[+DESCRIPTION?\bprintf\b writes each \astring\a operand to "
 | 
					"[+DESCRIPTION?\bprintf\b writes each \astring\a operand to "
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,7 +204,7 @@ struct shared
 | 
				
			||||||
	char		used_pos;	/* used positional parameter */\
 | 
						char		used_pos;	/* used positional parameter */\
 | 
				
			||||||
	char		universe; \
 | 
						char		universe; \
 | 
				
			||||||
	char		winch; \
 | 
						char		winch; \
 | 
				
			||||||
	char		inarith; 	/* set when in ((...)) */ \
 | 
						char		inarith; 	/* set when in POSIX arith context, i.e. leading zero = octal, e.g. in ((...)) */ \
 | 
				
			||||||
	short		arithrecursion;	/* current arithmetic recursion level */ \
 | 
						short		arithrecursion;	/* current arithmetic recursion level */ \
 | 
				
			||||||
	char		indebug; 	/* set when in debug trap */ \
 | 
						char		indebug; 	/* set when in debug trap */ \
 | 
				
			||||||
	unsigned char	ignsig;		/* ignored signal in subshell */ \
 | 
						unsigned char	ignsig;		/* ignored signal in subshell */ \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SH_RELEASE_FORK	"93u+m"		/* only change if you develop a new ksh93 fork */
 | 
					#define SH_RELEASE_FORK	"93u+m"		/* only change if you develop a new ksh93 fork */
 | 
				
			||||||
#define SH_RELEASE_SVER	"1.0.0-beta.2"	/* semantic version number: https://semver.org */
 | 
					#define SH_RELEASE_SVER	"1.0.0-beta.2"	/* semantic version number: https://semver.org */
 | 
				
			||||||
#define SH_RELEASE_DATE	"2021-09-12"	/* must be in this format for $((.sh.version)) */
 | 
					#define SH_RELEASE_DATE	"2021-09-13"	/* must be in this format for $((.sh.version)) */
 | 
				
			||||||
#define SH_RELEASE_CPYR	"(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
 | 
					#define SH_RELEASE_CPYR	"(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
 | 
					/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -470,6 +470,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
 | 
				
			||||||
	struct rand *rp;		/* current $RANDOM discipline function data */
 | 
						struct rand *rp;		/* current $RANDOM discipline function data */
 | 
				
			||||||
	unsigned int save_rand_seed;	/* parent shell $RANDOM seed */
 | 
						unsigned int save_rand_seed;	/* parent shell $RANDOM seed */
 | 
				
			||||||
	int save_rand_last;		/* last random number from $RANDOM in parent shell */
 | 
						int save_rand_last;		/* last random number from $RANDOM in parent shell */
 | 
				
			||||||
 | 
						char save_inarith;		/* flag indicating POSIX arithmetic context */
 | 
				
			||||||
	memset((char*)sp, 0, sizeof(*sp));
 | 
						memset((char*)sp, 0, sizeof(*sp));
 | 
				
			||||||
	sfsync(shp->outpool);
 | 
						sfsync(shp->outpool);
 | 
				
			||||||
	sh_sigcheck(shp);
 | 
						sh_sigcheck(shp);
 | 
				
			||||||
| 
						 | 
					@ -591,6 +592,9 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if(comsub)
 | 
							if(comsub)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								/* a comsub within an arithmetic expression must not itself be in an arithmetic context */
 | 
				
			||||||
 | 
								save_inarith = shp->inarith;
 | 
				
			||||||
 | 
								shp->inarith = 0;
 | 
				
			||||||
			/* disable job control */
 | 
								/* disable job control */
 | 
				
			||||||
			shp->spid = 0;
 | 
								shp->spid = 0;
 | 
				
			||||||
			sp->jobcontrol = job.jobcontrol;
 | 
								sp->jobcontrol = job.jobcontrol;
 | 
				
			||||||
| 
						 | 
					@ -734,6 +738,8 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
 | 
				
			||||||
			sh_close(sp->tmpfd);
 | 
								sh_close(sp->tmpfd);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		shp->fdstatus[1] = sp->fdstatus;
 | 
							shp->fdstatus[1] = sp->fdstatus;
 | 
				
			||||||
 | 
							/* restore POSIX arithmetic context flag */
 | 
				
			||||||
 | 
							shp->inarith = save_inarith;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(!shp->subshare)
 | 
						if(!shp->subshare)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -876,5 +876,27 @@ then
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
unset got
 | 
					unset got
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ======
 | 
				
			||||||
 | 
					# https://github.com/ksh93/ksh/issues/326
 | 
				
			||||||
 | 
					for m in u d i o x X
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						case $m in
 | 
				
			||||||
 | 
						o)	exp="10;21;32;" ;;
 | 
				
			||||||
 | 
						x)	exp="8;11;1a;" ;;
 | 
				
			||||||
 | 
						X)	exp="8;11;1A;" ;;
 | 
				
			||||||
 | 
						*)	exp="8;17;26;" ;;
 | 
				
			||||||
 | 
						esac
 | 
				
			||||||
 | 
						got=${ printf "%$m;" 010 021 032; }
 | 
				
			||||||
 | 
						[[ $got == "$exp" ]] || err_exit "printf %$m does not recognize octal arguments" \
 | 
				
			||||||
 | 
							"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# https://github.com/ksh93/ksh/issues/326#issuecomment-917707463
 | 
				
			||||||
 | 
					exp=18
 | 
				
			||||||
 | 
					got=$(( $(integer x; x=010; echo $x) + 010 ))
 | 
				
			||||||
 | 
					#		       ^^^ decimal     ^^^ octal
 | 
				
			||||||
 | 
					[[ $got == "$exp" ]] || err_exit 'Integer with leading zero incorrectly interpreted as octal in non-POSIX arith context' \
 | 
				
			||||||
 | 
						"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ======
 | 
					# ======
 | 
				
			||||||
exit $((Errors<125?Errors:125))
 | 
					exit $((Errors<125?Errors:125))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue