Skip to content

Commit 1acaeae

Browse files
committed
Fix UB in macro.c and streval.c
Clang with UBSan on macOS found these instances of undefined behaviour. These two files both contain the test (Sflong_t)d!=d to check if the value of a long double (Sfdouble_t) 'd' can be represented in a variable of type long long (Sflong_t). This test has undefined behaviour if isinf(d), if isnan(d), or if the value of d is smaller or greater than the minimum or maximum value that can be stored in an Sflong_t variable. So this commit adds tests for those conditions. The original test, (Sflong_t)d!=d, should now only be used to figure out if there is a decimal fraction, which should be well-defined behaviour. Note that LDBL_LLONG_MIN and LDBL_LLONG_MAX are defined in streval.h; they are LLONG_MIN and LLONG_MAX typecast to Sfdouble_t.
1 parent dd1efb4 commit 1acaeae

2 files changed

Lines changed: 5 additions & 3 deletions

File tree

src/cmd/ksh93/sh/macro.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2210,7 +2210,8 @@ static void comsubst(Mac_t *mp,Shnode_t* t, char type)
22102210
out_offset:
22112211
stkset(stkp,savptr,savtop);
22122212
*mp = savemac;
2213-
if((Sflong_t)num!=num)
2213+
/* must use <= >= not < >, as we have reduced precision at these sizes */
2214+
if(isinf(num) || isnan(num) || num <= LDBL_LLONG_MIN || num >= LDBL_LLONG_MAX || (Sflong_t)num!=num)
22142215
sfprintf(sh.strbuf,"%.*Lg",LDBL_DIG,num);
22152216
else if(num)
22162217
sfprintf(sh.strbuf,"%jd",(Sflong_t)num);

src/cmd/ksh93/sh/streval.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ Sfdouble_t arith_exec(Arith_t *ep)
240240
arith_error(node.value,ptr,ep->emode);
241241
*++sp = num;
242242
type = node.isfloat;
243-
if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
243+
if(isinf(num) || isnan(num) || num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
244244
type = 1;
245245
else
246246
{
@@ -250,7 +250,8 @@ Sfdouble_t arith_exec(Arith_t *ep)
250250
type = 2;
251251
d -= LDBL_LLONG_MAX;
252252
}
253-
if((Sflong_t)d!=d)
253+
/* must use <= >= not < >, as we have reduced precision at these sizes */
254+
if(d <= LDBL_LLONG_MIN || d >= LDBL_LLONG_MAX || (Sflong_t)d!=d)
254255
type = 1;
255256
}
256257
*++tp = type;

0 commit comments

Comments
 (0)