Skip to content
This repository was archived by the owner on Aug 24, 2025. It is now read-only.

Commit 5b0e7e5

Browse files
rjo12dennisguse
authored andcommitted
Bugfix: Off-by-one bug in subtracting UINT. Fixes #1557
1 parent d6cf8ba commit 5b0e7e5

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/androidTest/java/de/dennisguse/opentracks/sensors/UintUtilsTest.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,44 @@ public void diff() {
1111
assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT16_MAX));
1212
assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT16_MAX));
1313
assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT16_MAX));
14-
assertEquals(65534, UintUtils.diff(1, 2, UintUtils.UINT16_MAX));
15-
// assertEquals(65535, UintUtils.diff(0, 1, UintUtils.UINT16_MAX));
16-
assertEquals(65535, UintUtils.UINT16_MAX);
17-
14+
assertEquals(65535, UintUtils.diff(1, 2, UintUtils.UINT16_MAX)); /* unsigned 16 arithmetic is modulo UINT16_MAX + 1, not modulo UINT16_MAX */
1815
assertEquals(65530, UintUtils.diff(UintUtils.UINT16_MAX, 5, UintUtils.UINT16_MAX));
16+
17+
/* Test modulo arithmetic for arguments that are out of range */
18+
19+
if (false) { /* false means UintUtils.diff() throws if arguments out of range */
20+
assertEquals(0, UintUtils.diff(65537, 1, UintUtils.UINT16_MAX));
21+
assertEquals(0, UintUtils.diff(1, 65537, UintUtils.UINT16_MAX));
22+
assertEquals(0, UintUtils.diff(65537, 65537, UintUtils.UINT16_MAX));
23+
assertEquals(0, UintUtils.diff(-65535, 1, UintUtils.UINT16_MAX));
24+
assertEquals(0, UintUtils.diff(1, -65535, UintUtils.UINT16_MAX));
25+
assertEquals(0, UintUtils.diff(-65535, -65535, UintUtils.UINT16_MAX));
26+
assertEquals(0, UintUtils.diff(-65535, 65537, UintUtils.UINT16_MAX));
27+
assertEquals(0, UintUtils.diff(65537, -65535, UintUtils.UINT16_MAX));
28+
}
29+
30+
/* The following tests are the above, but for 32-bit unsigned. */
31+
32+
assertEquals(0, UintUtils.diff(1, 1, UintUtils.UINT32_MAX));
33+
assertEquals(1, UintUtils.diff(2, 1, UintUtils.UINT32_MAX));
34+
assertEquals(3, UintUtils.diff(5, 2, UintUtils.UINT32_MAX));
35+
assertEquals(4294967295L, UintUtils.diff(1, 2, UintUtils.UINT32_MAX));
36+
assertEquals(4294967290L, UintUtils.diff(UintUtils.UINT32_MAX, 5, UintUtils.UINT32_MAX));
37+
38+
if (false) { /* false means UintUtils.diff() throws if arguments out of range */
39+
assertEquals(0, UintUtils.diff(4294967297L, 1, UintUtils.UINT32_MAX));
40+
assertEquals(0, UintUtils.diff(1, 4294967297L, UintUtils.UINT32_MAX));
41+
assertEquals(0, UintUtils.diff(4294967297L, 4294967297L, UintUtils.UINT32_MAX));
42+
assertEquals(0, UintUtils.diff(-4294967295L, 1, UintUtils.UINT32_MAX));
43+
assertEquals(0, UintUtils.diff(1, -4294967295L, UintUtils.UINT32_MAX));
44+
assertEquals(0, UintUtils.diff(-4294967295L, -4294967295L, UintUtils.UINT32_MAX));
45+
assertEquals(0, UintUtils.diff(-4294967295L, 4294967297L, UintUtils.UINT32_MAX));
46+
assertEquals(0, UintUtils.diff(65537, -4294967297L, UintUtils.UINT32_MAX));
47+
}
1948
}
2049

2150
@Test
2251
public void realData() {
2352
assertEquals(1, UintUtils.diff(381616, 381615, UintUtils.UINT32_MAX));
2453
}
25-
}
54+
}

src/main/java/de/dennisguse/opentracks/sensors/UintUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ private UintUtils() {
1414
* @return diff
1515
*/
1616
public static long diff(long a, long b, final long UINT_MAX) {
17+
1718
if (a < 0 || b < 0) {
1819
throw new RuntimeException("a or b cannot be less than zero.");
1920
}
@@ -25,6 +26,6 @@ public static long diff(long a, long b, final long UINT_MAX) {
2526
return a - b;
2627
}
2728

28-
return (UINT_MAX - b) + a;
29+
return (UINT_MAX + 1 - b) + a;
2930
}
3031
}

0 commit comments

Comments
 (0)