Skip to content

Commit f80519a

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 c3fa4ef commit f80519a

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
@@ -2277,7 +2277,8 @@ static void comsubst(Mac_t *mp,Shnode_t* t, char type)
22772277
out_offset:
22782278
stkset(stkp,savptr,savtop);
22792279
*mp = savemac;
2280-
if((Sflong_t)num!=num)
2280+
/* must use <= >= not < >, as we have reduced precision at these sizes */
2281+
if(isinf(num) || isnan(num) || num <= LDBL_LLONG_MIN || num >= LDBL_LLONG_MAX || (Sflong_t)num!=num)
22812282
sfprintf(sh.strbuf,"%.*Lg",LDBL_DIG,num);
22822283
else if(num)
22832284
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)