From d9b6501667f4cd051020aa569945d10be38d87be Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Sat, 28 Dec 2024 19:55:05 -0800 Subject: [PATCH] Backport ksh93v- bugfix for the crash in types.sh This commit backports a bugfix from ksh93v- 2012-08-24 for a possible crash at the first strncmp in create_type(). This crash will occur if the size and/or alignment of Namval struct is changed (e.g., if np->nvsize or np->nvflag is upgraded to a larger data type). Thus far I can't reproduce this bug on the dev branch without changing the size of the Namval_t struct, but the root cause of the bug should be fixed nonetheless for correctness. I encountered this bug while experimenting with changing the size of Namval_t, which at the moment is primarily relevant to the unfinished local builtin (which needs to store a new NV_DYNAMIC flag in the variable node's nvflag set). Non-upstreamed commits for reference: https://github.com/JohnoKing/ksh/commit/3ca5470 (local-builtin branch) https://github.com/JohnoKing/ksh/commit/798d463 (expand-nvflags branch) https://github.com/JohnoKing/ksh/commit/e390adf (earlier iteration of this commit) Crash trace from ASan (unlike the one in the earlier expand-nvflags commit, this was retested against 0510264c with np->nvsize changed to uint64_t; it can also be reproduced if np->nvflags is enlargened instead): ================================================================= ==186087==ERROR: AddressSanitizer: SEGV on unknown address 0x000000001340 (pc 0x79c3ece88110 bp 0x7ffe576bd670 sp 0x7ffe576bcde0 T0) ==186087==The signal is caused by a READ memory access. #0 0x79c3ece88110 in strncmp /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:491 #1 0x79c3ec3460d0 in create_type /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/nvtype.c:486 #2 0x79c3ec4e2301 in create_tree /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/nvtree.c:74 #3 0x79c3ec4bb610 in nv_create /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:1238 #4 0x79c3ec4bf531 in nv_open /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:1451 #5 0x79c3ec4b0202 in nv_setlist /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/name.c:608 #6 0x79c3ec5819db in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1076 #7 0x79c3ec2ca5ee in b_dot_cmd /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/bltins/misc.c:324 src/cmd/ksh93/sh/nvtype.c: - Account for NV_MINSZ when setting the 'base' string to ensure no invalid reads occur because of changes in the alignment and/or size of Namval_t. - Additionally, store the return value from strlen in a size_t variable. --- src/cmd/ksh93/sh/nvtype.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c index 4587e6029e68..fc8d02335c8c 100644 --- a/src/cmd/ksh93/sh/nvtype.c +++ b/src/cmd/ksh93/sh/nvtype.c @@ -481,8 +481,8 @@ static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp n = (cp-1) -name; if(dp->numnodes && dp->strsize<0) { - char *base = (char*)np-sizeof(Dtlink_t); - int m=strlen(np->nvname); + char *base = (char*)np-(NV_MINSZ-sizeof(Dtlink_t)); + size_t m=strlen(np->nvname); while((nq=nv_namptr(base,++i)) && strncmp(nq->nvname,np->nvname,m)==0) { if(nq->nvname[m]=='.' && strncmp(name,&nq->nvname[m+1],n)==0 && nq->nvname[m+n+1]==0)