Skip to content

Commit

Permalink
Avoid integer undefined behavior (resolves #241)
Browse files Browse the repository at this point in the history
  • Loading branch information
lindstro committed Sep 18, 2024
1 parent b4c4696 commit 3eafd7c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 14 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Change Log

---

## Unreleased

### Fixed

- #241: Signed left shifts, integer overflow invoke undefined behavior.

---

## 1.0.1 (2023-12-15)

This patch release primarily addresses minor bug fixes and is needed to update
Expand Down
19 changes: 15 additions & 4 deletions src/template/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,27 @@ _t1(inv_lift, Int)(Int* p, ptrdiff_t s)

/*
** non-orthogonal transform
**
** ( 4 6 -4 -1) (x)
** 1/4 * ( 4 2 4 5) (y)
** ( 4 -2 4 -5) (z)
** ( 4 -6 -4 1) (w)
**
** original lifted version, which invokes UB due to signed left shift and
** integer overflow:
**
** y += w >> 1; w -= y >> 1;
** y += w; w <<= 1; w -= y;
** z += x; x <<= 1; x -= z;
** y += z; z <<= 1; z -= y;
** w += x; x <<= 1; x -= w;
*/

y += w >> 1; w -= y >> 1;
y += w; w <<= 1; w -= y;
z += x; x <<= 1; x -= z;
y += z; z <<= 1; z -= y;
w += x; x <<= 1; x -= w;
y += w; w -= y - w;
z += x; x -= z - x;
y += z; z -= y - z;
w += x; x -= w - x;

p -= s; *p = w;
p -= s; *p = z;
Expand Down
13 changes: 8 additions & 5 deletions src/template/revdecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,30 @@ static void _t2(rev_inv_xform, Int, DIMS)(Int* p);
static void
_t1(rev_inv_lift, Int)(Int* p, ptrdiff_t s)
{
Int x, y, z, w;
UInt x, y, z, w;
x = *p; p += s;
y = *p; p += s;
z = *p; p += s;
w = *p; p += s;

/*
** high-order Lorenzo transform (P4 Pascal matrix)
**
** ( 1 0 0 0) (x)
** ( 1 1 0 0) (y)
** ( 1 2 1 0) (z)
** ( 1 3 3 1) (w)
**
** unsigned arithmetic is used to avoid integer overflow
*/
w += z;
z += y; w += z;
y += x; z += y; w += z;

p -= s; *p = w;
p -= s; *p = z;
p -= s; *p = y;
p -= s; *p = x;
p -= s; *p = (Int)w;
p -= s; *p = (Int)z;
p -= s; *p = (Int)y;
p -= s; *p = (Int)x;
}

/* decode block of integers using reversible algorithm */
Expand Down
13 changes: 8 additions & 5 deletions src/template/revencode.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,30 @@ static void _t2(rev_fwd_xform, Int, DIMS)(Int* p);
static void
_t1(rev_fwd_lift, Int)(Int* p, ptrdiff_t s)
{
Int x, y, z, w;
UInt x, y, z, w;
x = *p; p += s;
y = *p; p += s;
z = *p; p += s;
w = *p; p += s;

/*
** high-order Lorenzo transform
**
** ( 1 0 0 0) (x)
** (-1 1 0 0) (y)
** ( 1 -2 1 0) (z)
** (-1 3 -3 1) (w)
**
** unsigned arithmetic is used to avoid integer overflow
*/
w -= z; z -= y; y -= x;
w -= z; z -= y;
w -= z;

p -= s; *p = w;
p -= s; *p = z;
p -= s; *p = y;
p -= s; *p = x;
p -= s; *p = (Int)w;
p -= s; *p = (Int)z;
p -= s; *p = (Int)y;
p -= s; *p = (Int)x;
}

/* return precision required to encode block reversibly */
Expand Down

0 comments on commit 3eafd7c

Please sign in to comment.