* [PATCH 1/2 v2] libdecnumber: fixed multiple potential access-out-of bounds errors by moving range conditions before reads.
@ 2024-02-03 19:31 Ian McCormack
2024-03-27 20:48 ` Ian McCormack
0 siblings, 1 reply; 2+ messages in thread
From: Ian McCormack @ 2024-02-03 19:31 UTC (permalink / raw)
To: gcc-patches
Multiple `for` loops across `libdecnumber` contain boolean expressions where memory is accessed prior to checking if the pointer is still within a valid range, which can lead to out-of-bounds reads.
This patch moves the range conditions to appear before the memory accesses in each conjunction so that these expressions short-circuit instead of performing an invalid read.
libdecnumber/ChangeLog
* In each `for` loop and `if` statement, all boolean expressions of the form `*ptr == value && in_range(ptr)` have been changed to `in_range(ptr) && *ptr == value`.
Bootstrapped on x86_64-pc-linux-gnu with no regressions.
---
libdecnumber/decBasic.c | 20 ++++++++++----------
libdecnumber/decCommon.c | 2 +-
libdecnumber/decNumber.c | 2 +-
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/libdecnumber/decBasic.c b/libdecnumber/decBasic.c
index 6319f66b25d..04833f2390d 100644
--- a/libdecnumber/decBasic.c
+++ b/libdecnumber/decBasic.c
@@ -341,7 +341,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
for (;;) { /* inner loop -- calculate quotient unit */
/* strip leading zero units from acc (either there initially or */
/* from subtraction below); this may strip all if exactly 0 */
- for (; *msua==0 && msua>=lsua;) msua--;
+ for (; msua>=lsua && *msua==0;) msua--;
accunits=(Int)(msua-lsua+1); /* [maybe 0] */
/* subtraction is only necessary and possible if there are as */
/* least as many units remaining in acc for this iteration as */
@@ -515,7 +515,7 @@ static decFloat * decDivide(decFloat *result, const decFloat *dfl,
/* (must also continue to original lsu for correct quotient length) */
if (lsua>acc+DIVACCLEN-DIVOPLEN) continue;
for (; msua>lsua && *msua==0;) msua--;
- if (*msua==0 && msua==lsua) break;
+ if (msua==lsua && *msua==0) break;
} /* outer loop */
/* all of the original operand in acc has been covered at this point */
@@ -1543,8 +1543,8 @@ decFloat * decFloatAdd(decFloat *result,
umsd=acc+COFF+DECPMAX-1; /* so far, so zero */
if (ulsd>umsd) { /* more to check */
umsd++; /* to align after checked area */
- for (; UBTOUI(umsd)==0 && umsd+3<ulsd;) umsd+=4;
- for (; *umsd==0 && umsd<ulsd;) umsd++;
+ for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
+ for (; umsd<ulsd && *umsd==0;) umsd++;
}
if (*umsd==0) { /* must be true zero (and diffsign) */
num.sign=0; /* assume + */
@@ -2087,10 +2087,10 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* remove leading zeros on both operands; this will save time later */
/* and make testing for zero trivial (tests are safe because acc */
/* and coe are rounded up to uInts) */
- for (; UBTOUI(hi->msd)==0 && hi->msd+3<hi->lsd;) hi->msd+=4;
- for (; *hi->msd==0 && hi->msd<hi->lsd;) hi->msd++;
- for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
- for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
+ for (; hi->msd+3<hi->lsd && UBTOUI(hi->msd)==0;) hi->msd+=4;
+ for (; hi->msd<hi->lsd && *hi->msd==0;) hi->msd++;
+ for (; lo->msd+3<lo->lsd && UBTOUI(lo->msd)==0;) lo->msd+=4;
+ for (; lo->msd<lo->lsd && *lo->msd==0;) lo->msd++;
/* if hi is zero then result will be lo (which has the smaller */
/* exponent), which also may need to be tested for zero for the */
@@ -2252,8 +2252,8 @@ decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
/* all done except for the special IEEE 754 exact-zero-result */
/* rule (see above); while testing for zero, strip leading */
/* zeros (which will save decFinalize doing it) */
- for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
- for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
+ for (; lo->msd+3<lo->lsd && UBTOUI(lo->msd)==0;) lo->msd+=4;
+ for (; lo->msd<lo->lsd && *lo->msd==0;) lo->msd++;
if (*lo->msd==0) { /* must be true zero (and diffsign) */
lo->sign=0; /* assume + */
if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign;
diff --git a/libdecnumber/decCommon.c b/libdecnumber/decCommon.c
index 6f7563de6e6..1f9fe4a1935 100644
--- a/libdecnumber/decCommon.c
+++ b/libdecnumber/decCommon.c
@@ -276,7 +276,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum *num,
/* [this is quite expensive] */
if (*umsd==0) {
for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
- for (; *umsd==0 && umsd<ulsd;) umsd++;
+ for (; umsd<ulsd && *umsd==0;) umsd++;
length=ulsd-umsd+1; /* recalculate */
}
drop=MAXI(length-DECPMAX, DECQTINY-num->exponent);
diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c
index 094bc51c14a..89baef15749 100644
--- a/libdecnumber/decNumber.c
+++ b/libdecnumber/decNumber.c
@@ -4505,7 +4505,7 @@ static decNumber * decDivideOp(decNumber *res,
for (;;) { /* inner forever loop */
/* strip leading zero units [from either pre-adjust or from */
/* subtract last time around]. Leave at least one unit. */
- for (; *msu1==0 && msu1>var1; msu1--) var1units--;
+ for (; msu1>var1 && *msu1==0; msu1--) var1units--;
if (var1units<var2ulen) break; /* var1 too low for subtract */
if (var1units==var2ulen) { /* unit-by-unit compare needed */
--
2.39.3 (Apple Git-145)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 1/2 v2] libdecnumber: fixed multiple potential access-out-of bounds errors by moving range conditions before reads.
2024-02-03 19:31 [PATCH 1/2 v2] libdecnumber: fixed multiple potential access-out-of bounds errors by moving range conditions before reads Ian McCormack
@ 2024-03-27 20:48 ` Ian McCormack
0 siblings, 0 replies; 2+ messages in thread
From: Ian McCormack @ 2024-03-27 20:48 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 6356 bytes --]
Hello—just pinging again about the following two patches I submitted. Each
fixes small access-out-of-bounds errors in libdecnumber.
https://gcc.gnu.org/pipermail/gcc-patches/2024-February/644840.html
https://gcc.gnu.org/pipermail/gcc-patches/2024-February/644910.html
Also, the documentation indicated that I should mention that I do not have
write access, since I'm a first-time contributor.
On Sat, Feb 3, 2024 at 2:31 PM Ian McCormack <icmccorm@gmail.com> wrote:
> Multiple `for` loops across `libdecnumber` contain boolean expressions
> where memory is accessed prior to checking if the pointer is still within a
> valid range, which can lead to out-of-bounds reads.
>
> This patch moves the range conditions to appear before the memory accesses
> in each conjunction so that these expressions short-circuit instead of
> performing an invalid read.
>
> libdecnumber/ChangeLog
> * In each `for` loop and `if` statement, all boolean expressions of
> the form `*ptr == value && in_range(ptr)` have been changed to
> `in_range(ptr) && *ptr == value`.
>
> Bootstrapped on x86_64-pc-linux-gnu with no regressions.
> ---
> libdecnumber/decBasic.c | 20 ++++++++++----------
> libdecnumber/decCommon.c | 2 +-
> libdecnumber/decNumber.c | 2 +-
> 3 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/libdecnumber/decBasic.c b/libdecnumber/decBasic.c
> index 6319f66b25d..04833f2390d 100644
> --- a/libdecnumber/decBasic.c
> +++ b/libdecnumber/decBasic.c
> @@ -341,7 +341,7 @@ static decFloat * decDivide(decFloat *result, const
> decFloat *dfl,
> for (;;) { /* inner loop -- calculate quotient unit */
> /* strip leading zero units from acc (either there initially or */
> /* from subtraction below); this may strip all if exactly 0 */
> - for (; *msua==0 && msua>=lsua;) msua--;
> + for (; msua>=lsua && *msua==0;) msua--;
> accunits=(Int)(msua-lsua+1); /* [maybe 0] */
> /* subtraction is only necessary and possible if there are as */
> /* least as many units remaining in acc for this iteration as */
> @@ -515,7 +515,7 @@ static decFloat * decDivide(decFloat *result, const
> decFloat *dfl,
> /* (must also continue to original lsu for correct quotient length) */
> if (lsua>acc+DIVACCLEN-DIVOPLEN) continue;
> for (; msua>lsua && *msua==0;) msua--;
> - if (*msua==0 && msua==lsua) break;
> + if (msua==lsua && *msua==0) break;
> } /* outer loop */
>
> /* all of the original operand in acc has been covered at this point */
> @@ -1543,8 +1543,8 @@ decFloat * decFloatAdd(decFloat *result,
> umsd=acc+COFF+DECPMAX-1; /* so far, so zero */
> if (ulsd>umsd) { /* more to check */
> umsd++; /* to align after checked area */
> - for (; UBTOUI(umsd)==0 && umsd+3<ulsd;) umsd+=4;
> - for (; *umsd==0 && umsd<ulsd;) umsd++;
> + for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
> + for (; umsd<ulsd && *umsd==0;) umsd++;
> }
> if (*umsd==0) { /* must be true zero (and diffsign) */
> num.sign=0; /* assume + */
> @@ -2087,10 +2087,10 @@ decFloat * decFloatFMA(decFloat *result, const
> decFloat *dfl,
> /* remove leading zeros on both operands; this will save time later */
> /* and make testing for zero trivial (tests are safe because acc */
> /* and coe are rounded up to uInts) */
> - for (; UBTOUI(hi->msd)==0 && hi->msd+3<hi->lsd;) hi->msd+=4;
> - for (; *hi->msd==0 && hi->msd<hi->lsd;) hi->msd++;
> - for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
> - for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
> + for (; hi->msd+3<hi->lsd && UBTOUI(hi->msd)==0;) hi->msd+=4;
> + for (; hi->msd<hi->lsd && *hi->msd==0;) hi->msd++;
> + for (; lo->msd+3<lo->lsd && UBTOUI(lo->msd)==0;) lo->msd+=4;
> + for (; lo->msd<lo->lsd && *lo->msd==0;) lo->msd++;
>
> /* if hi is zero then result will be lo (which has the smaller */
> /* exponent), which also may need to be tested for zero for the */
> @@ -2252,8 +2252,8 @@ decFloat * decFloatFMA(decFloat *result, const
> decFloat *dfl,
> /* all done except for the special IEEE 754 exact-zero-result */
> /* rule (see above); while testing for zero, strip leading */
> /* zeros (which will save decFinalize doing it) */
> - for (; UBTOUI(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
> - for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
> + for (; lo->msd+3<lo->lsd && UBTOUI(lo->msd)==0;) lo->msd+=4;
> + for (; lo->msd<lo->lsd && *lo->msd==0;) lo->msd++;
> if (*lo->msd==0) { /* must be true zero (and diffsign) */
> lo->sign=0; /* assume + */
> if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign;
> diff --git a/libdecnumber/decCommon.c b/libdecnumber/decCommon.c
> index 6f7563de6e6..1f9fe4a1935 100644
> --- a/libdecnumber/decCommon.c
> +++ b/libdecnumber/decCommon.c
> @@ -276,7 +276,7 @@ static decFloat * decFinalize(decFloat *df, bcdnum
> *num,
> /* [this is quite expensive] */
> if (*umsd==0) {
> for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
> - for (; *umsd==0 && umsd<ulsd;) umsd++;
> + for (; umsd<ulsd && *umsd==0;) umsd++;
> length=ulsd-umsd+1; /* recalculate */
> }
> drop=MAXI(length-DECPMAX, DECQTINY-num->exponent);
> diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c
> index 094bc51c14a..89baef15749 100644
> --- a/libdecnumber/decNumber.c
> +++ b/libdecnumber/decNumber.c
> @@ -4505,7 +4505,7 @@ static decNumber * decDivideOp(decNumber *res,
> for (;;) { /* inner forever loop */
> /* strip leading zero units [from either pre-adjust or from */
> /* subtract last time around]. Leave at least one unit. */
> - for (; *msu1==0 && msu1>var1; msu1--) var1units--;
> + for (; msu1>var1 && *msu1==0; msu1--) var1units--;
>
> if (var1units<var2ulen) break; /* var1 too low for subtract
> */
> if (var1units==var2ulen) { /* unit-by-unit compare
> needed */
> --
> 2.39.3 (Apple Git-145)
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-03-27 20:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-03 19:31 [PATCH 1/2 v2] libdecnumber: fixed multiple potential access-out-of bounds errors by moving range conditions before reads Ian McCormack
2024-03-27 20:48 ` Ian McCormack
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).