Skip to content

Commit 112ae75

Browse files
committed
Merge branch '2.11' into 2.12
2 parents 74ccb0b + b4db541 commit 112ae75

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -738,10 +738,13 @@ private final void _writeIntFull(int markerBase, int i) throws IOException
738738

739739
// Helper method that works like `writeNumber(long)` but DOES NOT
740740
// check internal output state. It does, however, check need for minimization
741-
private final void _writeLongNoCheck(long l) throws IOException {
741+
private final void _writeLongNoCheck(long l) throws IOException
742+
{
742743
if (_cfgMinimalInts) {
743744
if (l >= 0) {
744-
if (l <= 0x100000000L) {
745+
// 31-Mar-2021, tatu: [dataformats-cbor#269] Incorrect boundary check,
746+
// was off by one, resulting in truncation to 0
747+
if (l < 0x100000000L) {
745748
_writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
746749
return;
747750
}
@@ -1010,7 +1013,9 @@ public void writeNumber(long l) throws IOException {
10101013
_verifyValueWrite("write number");
10111014
if (_cfgMinimalInts) { // maybe 32 bits is enough?
10121015
if (l >= 0) {
1013-
if (l <= 0x100000000L) {
1016+
// 31-Mar-2021, tatu: [dataformats-cbor#269] Incorrect boundary check,
1017+
// was off by one, resulting in truncation to 0
1018+
if (l < 0x100000000L) {
10141019
_writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
10151020
return;
10161021
}

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

+13
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,19 @@ protected String _numberToName(int ch, boolean neg) throws IOException
815815
break;
816816
case 26:
817817
i = _decode32Bits();
818+
// [dataformats-binary#269] (and earlier [dataformats-binary#30]),
819+
// got some edge case to consider
820+
if (i < 0) {
821+
long l;
822+
if (neg) {
823+
long unsignedBase = (long) i & 0xFFFFFFFFL;
824+
l = -unsignedBase - 1L;
825+
} else {
826+
l = (long) i;
827+
l = l & 0xFFFFFFFFL;
828+
}
829+
return String.valueOf(l);
830+
}
818831
break;
819832
case 27:
820833
{

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

+24-9
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
{
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

+4
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

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Modules:
3030
(reported by Fabian M)
3131
#268: (smile) Handle sequence of Smile header markers without recursion
3232
(reported by Fabian M)
33+
#269: CBOR loses `Map` entries with specific `long` Map key values (32-bit boundary)
34+
(reported by Quantum64@github)
3335

3436
2.12.2 (03-Mar-2021)
3537

0 commit comments

Comments
 (0)