Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ PJ Fanning (@pjfanning)
* Contributed #763: (protobuf) Use `VarHandle` for multi-byte primitive reads
and writes in `ProtobufParser` / `ProtobufGenerator`
(3.3.0)
* Contributed #781: (smile) `SmileGenerator.writeNumber(String)` should validate
number length against configured `StreamReadConstraints`, not global defaults
(3.3.0)
3 changes: 3 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ implementations)
#767: (smile) Use more efficient `String` construction wrt "Compact Strings"
for "short" ASCII text values of async parser
(fix by @cowtowncoder, w/ Claude code)
#781: (smile) `SmileGenerator.writeNumber(String)` should validate number length
against configured `StreamReadConstraints`, not global defaults
(contributed by @pjfanning)

3.2.3 (not yet released)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2761,12 +2761,10 @@ protected UnsupportedOperationException _notSupported() {

/**
* We need access to some reader-side constraints for safety-check within
* number decoding for {@linl #writeNumber(String)}: for now we need to
* rely on global defaults; should be ok for basic safeguarding.
*
* @since 2.17
* number decoding for {@link #writeNumber(String)}: these are the ones
* configured for the underlying factory, accessed via {@link IOContext}.
*/
protected StreamReadConstraints _streamReadConstraints() {
return StreamReadConstraints.defaults();
return _ioContext.streamReadConstraints();
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package tools.jackson.dataformat.smile.gen;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.util.Arrays;

import org.junit.jupiter.api.Test;

import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.core.StreamReadConstraints;
import tools.jackson.core.exc.StreamConstraintsException;

import tools.jackson.dataformat.smile.*;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

public class SmileGeneratorNumbersTest
extends BaseTestForSmile
Expand Down Expand Up @@ -203,6 +210,42 @@ public void testNumbersAsString() throws Exception
assertEquals(10, out.toByteArray().length);
}

// [dataformats-binary#781]: `writeNumber(String)` should use the factory's
// `StreamReadConstraints` for its number-length guard, not global defaults
@Test
public void testNumbersAsStringLengthLimit() throws Exception
{
final int maxLen = 20;
SmileFactory f = smileFactoryBuilder(false, false, false)
.streamReadConstraints(StreamReadConstraints.builder()
.maxNumberLength(maxLen).build())
.build();
final String tooLongInt = "1".repeat(maxLen + 1);
final String tooLongDec = "1." + "1".repeat(maxLen - 1);

for (String num : new String[] { tooLongInt, tooLongDec }) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (SmileGenerator gen = (SmileGenerator) f.createGenerator(out)) {
gen.writeNumber(num);
fail("Should not pass for: "+num);
} catch (StreamConstraintsException e) {
verifyException(e, "Number value length (" + (maxLen + 1)
+ ") exceeds the maximum allowed (" + maxLen + ",");
}
}

// And conversely, one at the limit is fine
final String atLimit = "1".repeat(maxLen);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (SmileGenerator gen = (SmileGenerator) f.createGenerator(out)) {
gen.writeNumber(atLimit);
}
try (JsonParser p = f.createParser(out.toByteArray())) {
assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
assertEquals(new BigInteger(atLimit), p.getBigIntegerValue());
}
}

// [dataformats-binary#608]
@Test
public void testFloat32FromSpecEncoding() throws Exception
Expand Down