Skip to content

Commit 88015fa

Browse files
committed
Merge branch '2.12' into 2.13
2 parents b0dc480 + 112ae75 commit 88015fa

File tree

6 files changed

+114
-12
lines changed

6 files changed

+114
-12
lines changed

cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -746,10 +746,13 @@ private final void _writeIntFull(int markerBase, int i) throws IOException
746746

747747
// Helper method that works like `writeNumber(long)` but DOES NOT
748748
// check internal output state. It does, however, check need for minimization
749-
private final void _writeLongNoCheck(long l) throws IOException {
749+
private final void _writeLongNoCheck(long l) throws IOException
750+
{
750751
if (_cfgMinimalInts) {
751752
if (l >= 0) {
752-
if (l <= 0x100000000L) {
753+
// 31-Mar-2021, tatu: [dataformats-cbor#269] Incorrect boundary check,
754+
// was off by one, resulting in truncation to 0
755+
if (l < 0x100000000L) {
753756
_writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
754757
return;
755758
}
@@ -1018,7 +1021,9 @@ public void writeNumber(long l) throws IOException {
10181021
_verifyValueWrite("write number");
10191022
if (_cfgMinimalInts) { // maybe 32 bits is enough?
10201023
if (l >= 0) {
1021-
if (l <= 0x100000000L) {
1024+
// 31-Mar-2021, tatu: [dataformats-cbor#269] Incorrect boundary check,
1025+
// was off by one, resulting in truncation to 0
1026+
if (l < 0x100000000L) {
10221027
_writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
10231028
return;
10241029
}

cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,19 @@ protected String _numberToName(int ch, boolean neg) throws IOException
831831
break;
832832
case 26:
833833
i = _decode32Bits();
834+
// [dataformats-binary#269] (and earlier [dataformats-binary#30]),
835+
// got some edge case to consider
836+
if (i < 0) {
837+
long l;
838+
if (neg) {
839+
long unsignedBase = (long) i & 0xFFFFFFFFL;
840+
l = -unsignedBase - 1L;
841+
} else {
842+
l = (long) i;
843+
l = l & 0xFFFFFFFFL;
844+
}
845+
return String.valueOf(l);
846+
}
834847
break;
835848
case 27:
836849
{

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/mapper/NumberBeanTest.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import java.math.BigInteger;
66

77
import com.fasterxml.jackson.annotation.JsonUnwrapped;
8+
89
import com.fasterxml.jackson.core.JsonToken;
910
import com.fasterxml.jackson.core.JsonParser.NumberType;
11+
1012
import com.fasterxml.jackson.databind.ObjectMapper;
1113
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
1214
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
@@ -73,15 +75,28 @@ public void testLongRoundTrip() throws Exception
7375
100L, -200L,
7476
5000L, -3600L,
7577
Integer.MIN_VALUE, Integer.MAX_VALUE,
76-
1L + Integer.MAX_VALUE, -1L + Integer.MIN_VALUE,
77-
2330462449L, // from [dataformats-binary#30]
78-
Long.MIN_VALUE, Long.MAX_VALUE
79-
}) {
80-
LongBean input = new LongBean(v);
81-
byte[] b = MAPPER.writeValueAsBytes(input);
82-
LongBean result = MAPPER.readValue(b, LongBean.class);
83-
assertEquals(input.value, result.value);
78+
1L + Integer.MAX_VALUE, -1L + Integer.MIN_VALUE
79+
}) {
80+
_testLongRoundTrip(v);
8481
}
82+
83+
_testLongRoundTrip(2330462449L); // from [dataformats-binary#30]
84+
_testLongRoundTrip(0xFFFFFFFFL); // max positive uint32
85+
_testLongRoundTrip(-0xFFFFFFFFL);
86+
_testLongRoundTrip(0x100000000L);
87+
_testLongRoundTrip(-0x100000000L);
88+
_testLongRoundTrip(0x100000001L);
89+
_testLongRoundTrip(-0x100000001L);
90+
_testLongRoundTrip(Long.MIN_VALUE);
91+
_testLongRoundTrip(Long.MAX_VALUE);
92+
}
93+
94+
private void _testLongRoundTrip(long v) throws Exception
95+
{
96+
LongBean input = new LongBean(v);
97+
byte[] b = MAPPER.writeValueAsBytes(input);
98+
LongBean result = MAPPER.readValue(b, LongBean.class);
99+
assertEquals(input.value, result.value);
85100
}
86101

87102
// for [dataformats-binary#32] coercion of Float into Double
@@ -218,7 +233,7 @@ public void testNumberTypeRetainingBuffering() throws Exception
218233
assertToken(JsonToken.END_ARRAY, p.nextToken());
219234
}
220235
}
221-
236+
222237
// [databind#2784]
223238
public void testBigDecimalWithBuffering() throws Exception
224239
{
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.fasterxml.jackson.dataformat.cbor.mapper;
2+
3+
import java.util.*;
4+
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
7+
8+
// [dataformats-binary#269]
9+
public class NumberMap269Test extends CBORTestBase
10+
{
11+
static class TestData269 {
12+
Map<Long, String> map;
13+
14+
public TestData269 setMap(Map<Long, String> map) {
15+
this.map = map;
16+
return this;
17+
}
18+
19+
public Map<Long, String> getMap() {
20+
return map;
21+
}
22+
}
23+
24+
/*
25+
/**********************************************************
26+
/* Test methods
27+
/**********************************************************
28+
*/
29+
30+
private final ObjectMapper MAPPER = cborMapper();
31+
32+
// [dataformats-binary#269]
33+
public void testInt32BoundaryWithMapKey() throws Exception
34+
{
35+
// First, with specific reported combo:
36+
_testInt32BoundaryWithMapKey(4294967296L, -4294967296L);
37+
38+
// and then systematically couple of others (actually overlapping but...)
39+
final long MAX_POS_UINT32 = 0xFFFFFFFFL;
40+
final long MAX_POS_UINT32_PLUS_1 = MAX_POS_UINT32 + 1L;
41+
42+
_testInt32BoundaryWithMapKey(MAX_POS_UINT32, -MAX_POS_UINT32);
43+
_testInt32BoundaryWithMapKey(MAX_POS_UINT32_PLUS_1,
44+
-MAX_POS_UINT32_PLUS_1);
45+
46+
_testInt32BoundaryWithMapKey(MAX_POS_UINT32_PLUS_1 + 1L,
47+
-MAX_POS_UINT32_PLUS_1 - 1L);
48+
}
49+
50+
private void _testInt32BoundaryWithMapKey(long key1, long key2) throws Exception
51+
{
52+
Map<Long, String> map = new LinkedHashMap<>();
53+
map.put(key1, "hello");
54+
map.put(key2, "world");
55+
TestData269 input = new TestData269().setMap(map);
56+
57+
byte[] cborDoc = MAPPER.writeValueAsBytes(input);
58+
59+
TestData269 result = MAPPER.readValue(cborDoc, TestData269.class);
60+
61+
assertEquals(input.map, result.map);
62+
}
63+
}

release-notes/CREDITS-2.x

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ Jonas Konrad (yawkat@github)
141141
most compact form for all integers
142142
(2.11.0)
143143

144+
Dylan (Quantum64@github)
145+
* Reported #269: CBOR loses `Map` entries with specific `long` Map key values (32-bit boundary)
146+
(2.11.5 / 2.12.3)
147+
144148
Michael Liedtke (mcliedtke@github)
145149

146150
* Contributed fix for #212: (ion) Optimize `IonParser.getNumberType()` using

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Modules:
4040
(reported by Fabian M)
4141
#268: (smile) Handle sequence of Smile header markers without recursion
4242
(reported by Fabian M)
43+
#269: CBOR loses `Map` entries with specific `long` Map key values (32-bit boundary)
44+
(reported by Quantum64@github)
4345

4446
2.12.2 (03-Mar-2021)
4547

0 commit comments

Comments
 (0)