From cb9bf87c8d5979ae870668bd688ad4013907d871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sugawara=20=28=E2=88=A9=EF=BD=80-=C2=B4=29?= =?UTF-8?q?=E2=8A=83=E2=94=81=E7=82=8E=E7=82=8E=E7=82=8E=E7=82=8E=E7=82=8E?= Date: Mon, 11 May 2026 17:54:12 -0700 Subject: [PATCH 1/3] Add parameterized tests covering all ASCII-optimization exit paths in CBORParser These test were missing from the original pull request #568, and caused that at least three bugs were found that have been already missed. Adding now to ensure that no regressions are introduced. Each test generates a string with a controlled ASCII prefix followed by unicode, encodes it to CBOR, then decodes via both byte[] and throttled InputStream to exercise both _finishShortText and _finishLongTextAscii/_finishChunkedTextAscii paths. --- .../jackson/dataformat/cbor/CBORParser.java | 27 +- .../cbor/parse/AsciiTextCornerCasesTest.java | 222 +++++++++++++ .../cbor/parse/ParseLongAsciiTextTest.java | 43 --- .../parse/TruncatedLongAsciiTextTest.java | 100 ++++++ .../data/macbeth-snippet-chunked.cbor | 298 ------------------ .../data/macbeth-snippet-non-chunked.cbor | 296 ----------------- .../test/resources/data/macbeth-snippet.txt | 296 ----------------- 7 files changed, 336 insertions(+), 946 deletions(-) create mode 100644 cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java delete mode 100644 cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParseLongAsciiTextTest.java create mode 100644 cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java delete mode 100644 cbor/src/test/resources/data/macbeth-snippet-chunked.cbor delete mode 100644 cbor/src/test/resources/data/macbeth-snippet-non-chunked.cbor delete mode 100644 cbor/src/test/resources/data/macbeth-snippet.txt diff --git a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java index 533db5e5b..1ab29712c 100644 --- a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java +++ b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java @@ -2632,6 +2632,9 @@ private final int _finishLongTextAscii(int len) throws IOException // load as much input as possible int size = Math.min(len, Math.min((outBuf.length - outPtr), input.length)); if (!_tryToLoadToHaveAtLeast(size)) { + // [dataformats-binary#568]: sync TextBuffer before returning so + // the caller sees any chars already written in previous iterations. + _textBuffer.setCurrentLength(outPtr); return len; } int outEnd = size + outPtr; @@ -2775,20 +2778,24 @@ private final boolean _finishChunkedTextAscii() throws IOException char[] outBuf = _textBuffer.getBufferWithoutReset(); int outEnd = outBuf.length; while (true) { - // besides of which just need to ensure there's content - _loadMoreForChunkIfNeeded(); + // Ensure we have chunk data to consume + if (_inputPtr >= _chunkEnd) { + if (_chunkLeft == 0) { + _textBuffer.setCurrentLength(outPtr); + return true; + } + _loadMoreForChunkIfNeeded(); + } - // Find the size of the loop - int inSize = _chunkEnd - _inputPtr; + int inSize = _chunkEnd - _inputPtr; int outSize = outEnd - outPtr; int inputPtr = _inputPtr; int inputPtrEnd = _inputPtr + Math.min(inSize, outSize); int i = 0; - // loop with copying what we can. + // Tight loop to copy ASCII bytes while (inputPtr < inputPtrEnd && i >= 0) { i = input[inputPtr++]; - char val = (char) i; - outBuf[outPtr++] = val; + outBuf[outPtr++] = (char) i; } _inputPtr = inputPtr; @@ -2796,7 +2803,6 @@ private final boolean _finishChunkedTextAscii() throws IOException // Found a non-ascii char, correct pointers and return to the caller. _inputPtr -= 1; _textBuffer.setCurrentLength(outPtr - 1); - // return false to signal this to the calling code to allow the multi-byte code-path to kick. return false; } // Need more room? @@ -2805,11 +2811,6 @@ private final boolean _finishChunkedTextAscii() throws IOException outPtr = 0; outEnd = outBuf.length; } - if (_inputPtr < _chunkEnd || _chunkLeft > 0) { - continue; - } - _textBuffer.setCurrentLength(outPtr); - return true; } } diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java new file mode 100644 index 000000000..3385dea9c --- /dev/null +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java @@ -0,0 +1,222 @@ +package com.fasterxml.jackson.dataformat.cbor.parse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; +import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; +import com.fasterxml.jackson.dataformat.cbor.CBORParser; +import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; +import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Parameterized tests covering all ASCII-optimization exit paths in CBORParser: + * + * 1. _finishShortText: text fits in I/O buffer, ASCII fast-path + fallback to multi-byte + * 2. _finishLongTextAscii: text exceeds I/O buffer, iterates with buffer growth + * - Exit (B): non-ASCII byte found mid-iteration + * - Exit (C): all bytes consumed normally + * - Exercises TextBuffer segment growth (500→750→1125→...→8538→...) + * 3. _finishChunkedTextAscii: chunked text, ASCII fast-path per chunk + * + * Each test generates a string with a controlled ASCII prefix followed by unicode, + * encodes it to CBOR, then decodes via both byte[] and throttled InputStream to + * exercise both _finishShortText and _finishLongTextAscii/_finishChunkedTextAscii paths. + * + * Sizes are chosen to hit TextBuffer segment boundaries and I/O buffer boundaries: + * - Small (< I/O buffer): exercises _finishShortText + * - Medium (> I/O buffer but < first segment regrowth): exercises first iterations + * - Large (forces multiple segment growths): exercises finishCurrentSegment transitions + * - XL (segment grows past I/O buffer size): exercises partial-fill iterations + * + * NOTE: Each test creates a fresh CBORFactory via cborFactory() to ensure the + * BufferRecycler does not carry over grown char[] buffers from previous tests. + * The recycler retains the largest buffer returned to it, which would change the + * initial TextBuffer segment size and alter which code paths are exercised. + */ +public class AsciiTextCornerCasesTest extends CBORTestBase +{ + // TextBuffer segment sizes: 500, 750, 1125, 1687, 2530, 3795, 5692, 8538, 12807... + // I/O buffer size: 8000 + // Key boundaries to test around: + private static final int IO_BUF = 8000; + private static final int SEG_0 = 500; // initial segment + private static final int SEG_1 = 750; + private static final int SEG_2 = 1125; + private static final int SEG_7 = 8538; // first segment > I/O buffer + private static final int CUMULATIVE_TO_SEG_7 = 16279; // total chars to fill segments 0-6 + + static Stream asciiPrefixSizes() { + List args = new ArrayList<>(); + int[] sizes = { + // _finishShortText path (fits in I/O buffer) + 1, 10, 100, SEG_0 - 1, SEG_0, SEG_0 + 1, + SEG_1, SEG_2, 2000, 4000, 7000, IO_BUF - 1, + + // _finishLongTextAscii path (exceeds I/O buffer) + IO_BUF, IO_BUF + 1, IO_BUF + 500, + // Forces multiple segment growths + IO_BUF + SEG_0 + SEG_1, + CUMULATIVE_TO_SEG_7 - 1, + CUMULATIVE_TO_SEG_7, + CUMULATIVE_TO_SEG_7 + 1, + // Segment larger than I/O buffer (partial fill, no finishCurrentSegment) + CUMULATIVE_TO_SEG_7 + IO_BUF - 1, + CUMULATIVE_TO_SEG_7 + IO_BUF, + CUMULATIVE_TO_SEG_7 + IO_BUF + 1, + // Even larger: forces segment to grow again after partial fill + CUMULATIVE_TO_SEG_7 + SEG_7, + CUMULATIVE_TO_SEG_7 + SEG_7 + IO_BUF, + // 50K+ to force many regrowths + 50000 + }; + for (int asciiPrefix : sizes) { + args.add(Arguments.of(asciiPrefix, "pure_ascii")); + // With unicode suffix (exercises non-ASCII exit path B) + args.add(Arguments.of(asciiPrefix, "ascii_then_unicode")); + } + return args.stream(); + } + + @ParameterizedTest(name = "asciiPrefix={0}, flavor={1}") + @MethodSource("asciiPrefixSizes") + public void testNonChunkedViaByteArray(int asciiPrefix, String flavor) throws Exception + { + String input = buildTestString(asciiPrefix, flavor); + CBORFactory f = cborFactory(); + byte[] cbor = encodeCbor(f, input); + + // byte[] path: exercises _finishShortText for small, _finishLongText for large + try (CBORParser p = cborParser(f, cbor)) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(input, p.getText()); + } + } + + @ParameterizedTest(name = "asciiPrefix={0}, flavor={1}") + @MethodSource("asciiPrefixSizes") + public void testNonChunkedViaStream(int asciiPrefix, String flavor) throws Exception + { + String input = buildTestString(asciiPrefix, flavor); + CBORFactory f = cborFactory(); + byte[] cbor = encodeCbor(f, input); + + // InputStream path with throttling: forces _finishLongTextAscii for texts > I/O buffer + try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 997))) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(input, p.getText()); + } + } + + @ParameterizedTest(name = "asciiPrefix={0}, flavor={1}") + @MethodSource("asciiPrefixSizes") + public void testChunkedViaStream(int asciiPrefix, String flavor) throws Exception + { + String input = buildTestString(asciiPrefix, flavor); + CBORFactory f = cborFactory(); + byte[] cbor = encodeChunkedCbor(input); + + // Chunked encoding exercises _finishChunkedTextAscii + try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 997))) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(input, p.getText()); + } + } + + /** + * Tests that re-using the same parser across multiple strings exercises + * TextBuffer regrowth correctly (segments grow and are reused across getText calls). + */ + @ParameterizedTest(name = "asciiPrefix={0}, flavor={1}") + @MethodSource("asciiPrefixSizes") + public void testRepeatedParsesWithBufferGrowth(int asciiPrefix, String flavor) throws Exception + { + String input = buildTestString(asciiPrefix, flavor); + CBORFactory f = cborFactory(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (CBORGenerator gen = cborGenerator(f, bos)) { + gen.writeStartArray(); + gen.writeString(input); + gen.writeString(input); + gen.writeString(input); + gen.writeEndArray(); + } + byte[] cbor = bos.toByteArray(); + + try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 997))) { + assertEquals(JsonToken.START_ARRAY, p.nextToken()); + for (int i = 0; i < 3; i++) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(input, p.getText(), + "Mismatch on iteration " + i + " (buffer regrowth issue?)"); + } + assertEquals(JsonToken.END_ARRAY, p.nextToken()); + } + } + + private String buildTestString(int asciiPrefix, String flavor) { + if ("pure_ascii".equals(flavor)) { + return generateLongAsciiString(asciiPrefix); + } + // ascii_then_unicode: ASCII prefix + unicode suffix + return generateUnicodeStringWithAsciiPrefix(asciiPrefix, asciiPrefix + 200); + } + + private byte[] encodeCbor(CBORFactory f, String text) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (CBORGenerator gen = cborGenerator(f, bos)) { + gen.writeString(text); + } + return bos.toByteArray(); + } + + private byte[] encodeChunkedCbor(String text) throws IOException { + byte[] utf8 = text.getBytes("UTF-8"); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(0x7F); // indefinite-length text + int chunkSize = 997; + int offset = 0; + while (offset < utf8.length) { + int end = Math.min(offset + chunkSize, utf8.length); + // Don't split multi-byte UTF-8 sequences + while (end < utf8.length && (utf8[end] & 0xC0) == 0x80) { + end--; + } + int len = end - offset; + writeChunkHeader(bos, len); + bos.write(utf8, offset, len); + offset = end; + } + bos.write(0xFF); // break + return bos.toByteArray(); + } + + private static void writeChunkHeader(ByteArrayOutputStream bos, int len) { + if (len <= 23) { + bos.write(0x60 | len); + } else if (len <= 0xFF) { + bos.write(0x78); + bos.write(len); + } else if (len <= 0xFFFF) { + bos.write(0x79); + bos.write((len >> 8) & 0xFF); + bos.write(len & 0xFF); + } else { + bos.write(0x7A); + bos.write((len >> 24) & 0xFF); + bos.write((len >> 16) & 0xFF); + bos.write((len >> 8) & 0xFF); + bos.write(len & 0xFF); + } + } +} diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParseLongAsciiTextTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParseLongAsciiTextTest.java deleted file mode 100644 index 46e39948a..000000000 --- a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParseLongAsciiTextTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fasterxml.jackson.dataformat.cbor.parse; - -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; - -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.dataformat.cbor.CBORFactory; -import com.fasterxml.jackson.dataformat.cbor.CBORParser; -import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class ParseLongAsciiTextTest extends CBORTestBase -{ - private final CBORFactory CBOR_F = cborFactory(); - - @Test - public void testLongNonChunkedAsciiText() throws Exception { - // run several times to allow the internal buffers - // to grow - for (int x = 0; x < 3 ; x++) { - try (CBORParser p = CBOR_F.createParser(this.getClass().getResourceAsStream("/data/macbeth-snippet-non-chunked.cbor"))) { - assertEquals(JsonToken.VALUE_STRING, p.nextToken()); - String expected = new String(readResource("/data/macbeth-snippet.txt"), "UTF-8"); - assertEquals(expected, p.getText()); - } - } - } - - @Test - public void testLongChunkedAsciiText() throws Exception { - // run several times to allow the internal buffers - // to grow - for (int x = 0; x < 3 ; x++) { - try (CBORParser p = CBOR_F.createParser(this.getClass().getResourceAsStream("/data/macbeth-snippet-chunked.cbor"))) { - assertEquals(JsonToken.VALUE_STRING, p.nextToken()); - String expected = new String(readResource("/data/macbeth-snippet.txt"), StandardCharsets.UTF_8); - assertEquals(expected, p.getText()); - } - } - } -} diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java new file mode 100644 index 000000000..ec34e916d --- /dev/null +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java @@ -0,0 +1,100 @@ +package com.fasterxml.jackson.dataformat.cbor.parse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; +import com.fasterxml.jackson.dataformat.cbor.CBORParser; +import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; +import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test for missing setCurrentLength on the early-return path in _finishLongTextAscii + * when _tryToLoadToHaveAtLeast returns false (stream ends prematurely). + * + * The bug exists in the code (outPtr > 0 but setCurrentLength not called), but in + * practice it's masked because the caller _finishLongText then tries to read the + * remaining bytes via _nextByte() which throws on EOF before the corrupted TextBuffer + * is ever converted to a String. + * + * These tests document the behavior and verify correctness on both truncated and + * valid long ASCII input via throttled streams. + */ +public class TruncatedLongAsciiTextTest extends CBORTestBase +{ + /** + * Verifies that truncated long ASCII text results in a clean exception. + */ + @Test + public void testTruncatedAsciiThrowsCleanly() throws Exception + { + // Grow TextBuffer past I/O buffer size, then truncate + final int actualPayload = 16279 + 8000; + final int declaredLen = actualPayload + 5000; + + CBORFactory f = cborFactory(); + byte[] cbor = buildTruncatedCborText(declaredLen, actualPayload); + + try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 2000))) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + assertThrows(StreamReadException.class, () -> p.getText()); + } + } + + /** + * Verifies that a long ASCII text that fits exactly in the delivered bytes + * is decoded correctly even when the TextBuffer segment has grown past the + * I/O buffer size (exercises the partial-fill normal exit path). + */ + @Test + public void testLongAsciiExactLengthDecodedCorrectly() throws Exception + { + final int len = 25000; + + CBORFactory f = cborFactory(); + byte[] cbor = buildCborText(len); + + try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 2000))) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + String text = p.getText(); + assertEquals(len, text.length()); + String expected = new String(new char[len]).replace('\0', 'A'); + assertEquals(expected, text); + } + } + + private static byte[] buildTruncatedCborText(int declaredLen, int actualPayload) throws IOException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(0x7A); + bos.write((declaredLen >> 24) & 0xFF); + bos.write((declaredLen >> 16) & 0xFF); + bos.write((declaredLen >> 8) & 0xFF); + bos.write(declaredLen & 0xFF); + byte[] payload = new byte[actualPayload]; + Arrays.fill(payload, (byte) 'A'); + bos.write(payload); + return bos.toByteArray(); + } + + private static byte[] buildCborText(int len) throws IOException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(0x7A); + bos.write((len >> 24) & 0xFF); + bos.write((len >> 16) & 0xFF); + bos.write((len >> 8) & 0xFF); + bos.write(len & 0xFF); + byte[] payload = new byte[len]; + Arrays.fill(payload, (byte) 'A'); + bos.write(payload); + return bos.toByteArray(); + } +} diff --git a/cbor/src/test/resources/data/macbeth-snippet-chunked.cbor b/cbor/src/test/resources/data/macbeth-snippet-chunked.cbor deleted file mode 100644 index 95d85ad17..000000000 --- a/cbor/src/test/resources/data/macbeth-snippet-chunked.cbor +++ /dev/null @@ -1,298 +0,0 @@ -yœThe Tragedy of Macbeth, often shortened to Macbeth, is a tragedy by William Shakespeare, estimated to have been first performed in 1606 ---- -Act I, Scene - -A desert place. ---- - -First Witch. When shall we three meet again -In thunder, lightning, or in rain? -Second Witch. When the hurlyburly's done, -When the battle's lost and won. -Third Witch. That will be ere the set of sun. -First Witch. Where the place? -Second Witch. Upon the heath. -Third Witch. There to meet with Macbeth. -First Witch. I come, Graymalkin! -Second Witch. Paddock calls. -Third Witch. Anon. -All. Fair is foul, and foul is fair: -Hover through the fog and filthy air. - ---- -Act I, Scene - -A camp near Forres. ---- - -Duncan. What bloody man is that? He can report, -As seemeth by his plight, of the revolt -The newest state. -Malcolm. This is the sergeant -Who like a good and hardy soldier fought -'Gainst my captivity. Hail, brave friend! -Say to the king the knowledge of the broil -As thou didst leave it. -Sergeant. Doubtful it stood; -As two spent swimmers, that do cling together -And choke their art. The merciless Macdonwald- -Worthy to be a rebel, for to that -The multiplying villanies of nature -Do swarm upon him-from the western isles -Of kerns and gallowglasses is supplied; -And fortune, on his damned quarrel smiling, -Show'd like a rebel's whore: but all's too weak: -For brave Macbeth-well he deserves that name- -Disdaining fortune, with his brandish'd steel, -Which smoked with bloody execution, -Like valour's minion carved out his passage -Till he faced the slave; -Which ne'er shook hands, nor bade farewell to him, -Till he unseam'd him from the nave to the chaps, -And fix'd his head upon our battlements. -Duncan. O valiant cousin! worthy gentleman! -Sergeant. As whence the sun 'gins his reflection -Shipwrecking storms and direful thunders break, -So from that spring whence comfort seem'd to come -Discomfort swells. Mark, king of Scotland, mark: -No sooner justice had with valour arm'd -Compell'd these skipping kerns to trust their heels, -But the Norweyan lord surveying vantage, -With furbish'd arms and new supplies of men -Began a fresh assault. -Duncan. Dismay'd not this -Our captains, Macbeth and Banquo? -Sergeant. Yes; -As sparrows eagles, or the hare the lion. -If I say sooth, I must report they were -As cannons overcharged with double cracks, so they -Doubly redoubled strokes upon the foe: -Except they meant to bathe in reeking wounds, -Or memorise another Golgotha, -I cannot tell. -But I am faint, my gashes cry for help. -Duncan. So well thy words become thee as thy wounds; -They smack of honour both. Go get him surgeons. -[Exit Sergeant, attended] -Who comes here? -[Enter ROSS] - -Malcolm. The worthy thane of Ross. -Lennox. What a haste looks through his eyes! So should he look -That seems to speak things strange. -Ross. God save the king! -Duncan. Whence camest thou, worthy thane? -Ross. From Fife, great king; -Where the Norweyan banners flout the sky -And fan our people cold. Norway himself, -With terrible numbers, -Assisted by that most disloyal traitor -The thane of Cawdor, began a dismal conflict; -Till that Bellona's bridegroom, lapp'd in proof, -Confronted him with self-comparisons, -Point against point rebellious, arm 'gainst arm. -Curbing his lavish spirit: and, to conclude, -The victory fell on us. -Duncan. Great happiness! -Ross. That now -Sweno, the Norways' king, craves composition: -Nor would we deign him burial of his men -Till he disbursed at Saint Colme's inch -Ten thousand dollars to our general use. -Duncan. No more that thane of Cawdor shall deceive -Our bosom interest: go pronounce his present death, -And with his former title greet Macbeth. -Ross. I'll see it done. -Duncan. What he hath lost noble Macbeth hath won. -[Exeunt] - ---- -Act I, Scene - -A heath near Forres. - ---- -[Thunder. Enter the three Witches] - -First Witch. Where hast thou been, sister? -Second Witch. Killing swine. -Third Witch. Sister, where thou? -First Witch. A sailor's wife had chestnuts in her lap, -And munch'd, and munch'd, anyœd munch'd:- -'Give me,' quoth I: -'Aroint thee, witch!' the rump-fed ronyon cries. -Her husband's to Aleppo gone, master o' the Tiger: -But in a sieve I'll thither sail, -And, like a rat without a tail, -I'll do, I'll do, and I'll do. -Second Witch. I'll give thee a wind. -First Witch. Thou'rt kind. -Third Witch. And I another. -First Witch. I myself have all the other, -And the very ports they blow, -All the quarters that they know -I' the shipman's card. -I will drain him dry as hay: -Sleep shall neither night nor day -Hang upon his pent-house lid; -He shall live a man forbid: -Weary se'nnights nine times nine -Shall he dwindle, peak and pine: -Though his bark cannot be lost, -Yet it shall be tempest-tost. -Look what I have. -Second Witch. Show me, show me. -First Witch. Here I have a pilot's thumb, -Wreck'd as homeward he did come. -[Drum within] - -Third Witch. A drum, a drum! -Macbeth doth come. -All. The weird sisters, hand in hand, -Posters of the sea and land, -Thus do go about, about: -Thrice to thine and thrice to mine -And thrice again, to make up nine. -Peace! the charm's wound up. -[Enter MACBETH and BANQUO] - -Macbeth. So foul and fair a day I have not seen. -Banquo. How far is't call'd to Forres? What are these -So wither'd and so wild in their attire, -That look not like the inhabitants o' the earth, -And yet are on't? Live you? or are you aught -That man may question? You seem to understand me, -By each at once her chappy finger laying -Upon her skinny lips: you should be women, -And yet your beards forbid me to interpret -That you are so. -Macbeth. Speak, if you can: what are you? -First Witch. All hail, Macbeth! hail to thee, thane of Glamis! -Second Witch. All hail, Macbeth, hail to thee, thane of Cawdor! -Third Witch. All hail, Macbeth, thou shalt be king hereafter! -Banquo. Good sir, why do you start; and seem to fear -Things that do sound so fair? I' the name of truth, -Are ye fantastical, or that indeed -Which outwardly ye show? My noble partner -You greet with present grace and great prediction -Of noble having and of royal hope, -That he seems rapt withal: to me you speak not. -If you can look into the seeds of time, -And say which grain will grow and which will not, -Speak then to me, who neither beg nor fear -Your favours nor your hate. -First Witch. Hail! -Second Witch. Hail! -Third Witch. Hail! -First Witch. Lesser than Macbeth, and greater. -Second Witch. Not so happy, yet much happier. -Third Witch. Thou shalt get kings, though thou be none: -So all hail, Macbeth and Banquo! -First Witch. Banquo and Macbeth, all hail! -Macbeth. Stay, you imperfect speakers, tell me more: -By Sinel's death I know I am thane of Glamis; -But how of Cawdor? the thane of Cawdor lives, -A prosperous gentleman; and to be king -Stands not within the prospect of belief, -No more than to be Cawdor. Say from whence -You owe this strange intelligence? or why -Upon this blasted heath you stop our way -With such prophetic greeting? Speak, I charge you. -[Witches vanish] - -Banquo. The earth hath bubbles, as the water has, -And these are of them. Whither are they vanish'd? -Macbeth. Into the air; and what seem'd corporal melted -As breath into the wind. Would they had stay'd! -Banquo. Were such things here as we do speak about? -Or have we eaten on the insane root -That takes the reason prisoner? -Macbeth. Your children shall be kings. -Banquo. You shall be king. -Macbeth. And thane of Cawdor too: went it not so? -Banquo. To the selfsame tune and words. Who's here? -[Enter ROSS and ANGUS] - -Ross. The king hath happily received, Macbeth, -The news of thy success; and when he reads -Thy personal venture in the rebels' fight, -His wonders and his praises do contend -Which should be thine or his: silenced with that, -In viewing o'er the rest o' the selfsame day, -He finds thee in the stout Norweyan ranks, -Nothing afeard of what thyself didst make, -Strange images of death. As thick as hail -Came post with post; and every one did bear -Thy praises in his kingdom's great defence, -And pour'd them down before himy -f. -Angus. We are sent -To give thee from our royal master thanks; -Only to herald thee into his sight, -Not pay thee. -Ross. And, for an earnest of a greater honour, -He bade me, from him, call thee thane of Cawdor: -In which addition, hail, most worthy thane! -For it is thine. -Banquo. What, can the devil speak true? -Macbeth. The thane of Cawdor lives: why do you dress me -In borrow'd robes? -Angus. Who was the thane lives yet; -But under heavy judgment bears that life -Which he deserves to lose. Whether he was combined -With those of Norway, or did line the rebel -With hidden help and vantage, or that with both -He labour'd in his country's wreck, I know not; -But treasons capital, confess'd and proved, -Have overthrown him. -Macbeth. [Aside] Glamis, and thane of Cawdor! -The greatest is behind. -[To ROSS and ANGUS] -Thanks for your pains. -[To BANQUO] -Do you not hope your children shall be kings, -When those that gave the thane of Cawdor to me -Promised no less to them? -Banquo. That trusted home -Might yet enkindle you unto the crown, -Besides the thane of Cawdor. But 'tis strange: -And oftentimes, to win us to our harm, -The instruments of darkness tell us truths, -Win us with honest trifles, to betray's -In deepest consequence. -Cousins, a word, I pray you. -Macbeth. [Aside]. Two truths are told, -As happy prologues to the swelling act -Of the imperial theme.-I thank you, gentlemen. -[Aside] This supernatural soliciting] -Cannot be ill, cannot be good: if ill, -Why hath it given me earnest of success, -Commencing in a truth? I am thane of Cawdor: -If good, why do I yield to that suggestion -Whose horrid image doth unfix my hair -And make my seated heart knock at my ribs, -Against the use of nature? Present fears -Are less than horrible imaginings: -My thought, whose murder yet is but fantastical, -Shakes so my single state of man that function -Is smother'd in surmise, and nothing is -But what is not. -Banquo. Look, how our partner's rapt. -Macbeth. [Aside] If chance will have me king, why, chance may crown me, -Without my stir. -Banquo. New horrors come upon him, -Like our strange garments, cleave not to their mould -But with the aid of use. -Macbeth. [Aside] Come what come may, -Time and the hour runs through the roughest day. -Banquo. Worthy Macbeth, we stay upon your leisure. -Macbeth. Give me your favour: my dull brain was wrought -With things forgotten. Kind gentlemen, your pains -Are register'd where every day I turn -The leaf to read them. Let us toward the king. -Think upon what hath chanced, and, at more time, -The interim having weigh'd it, let us speak -Our free hearts each to other. -Banquo. Very gladly. -Macbeth. Till then, enough. Come, friends. -ÿ \ No newline at end of file diff --git a/cbor/src/test/resources/data/macbeth-snippet-non-chunked.cbor b/cbor/src/test/resources/data/macbeth-snippet-non-chunked.cbor deleted file mode 100644 index b67c42e16..000000000 --- a/cbor/src/test/resources/data/macbeth-snippet-non-chunked.cbor +++ /dev/null @@ -1,296 +0,0 @@ -y)žThe Tragedy of Macbeth, often shortened to Macbeth, is a tragedy by William Shakespeare, estimated to have been first performed in 1606 ---- -Act I, Scene - -A desert place. ---- - -First Witch. When shall we three meet again -In thunder, lightning, or in rain? -Second Witch. When the hurlyburly's done, -When the battle's lost and won. -Third Witch. That will be ere the set of sun. -First Witch. Where the place? -Second Witch. Upon the heath. -Third Witch. There to meet with Macbeth. -First Witch. I come, Graymalkin! -Second Witch. Paddock calls. -Third Witch. Anon. -All. Fair is foul, and foul is fair: -Hover through the fog and filthy air. - ---- -Act I, Scene - -A camp near Forres. ---- - -Duncan. What bloody man is that? He can report, -As seemeth by his plight, of the revolt -The newest state. -Malcolm. This is the sergeant -Who like a good and hardy soldier fought -'Gainst my captivity. Hail, brave friend! -Say to the king the knowledge of the broil -As thou didst leave it. -Sergeant. Doubtful it stood; -As two spent swimmers, that do cling together -And choke their art. The merciless Macdonwald- -Worthy to be a rebel, for to that -The multiplying villanies of nature -Do swarm upon him-from the western isles -Of kerns and gallowglasses is supplied; -And fortune, on his damned quarrel smiling, -Show'd like a rebel's whore: but all's too weak: -For brave Macbeth-well he deserves that name- -Disdaining fortune, with his brandish'd steel, -Which smoked with bloody execution, -Like valour's minion carved out his passage -Till he faced the slave; -Which ne'er shook hands, nor bade farewell to him, -Till he unseam'd him from the nave to the chaps, -And fix'd his head upon our battlements. -Duncan. O valiant cousin! worthy gentleman! -Sergeant. As whence the sun 'gins his reflection -Shipwrecking storms and direful thunders break, -So from that spring whence comfort seem'd to come -Discomfort swells. Mark, king of Scotland, mark: -No sooner justice had with valour arm'd -Compell'd these skipping kerns to trust their heels, -But the Norweyan lord surveying vantage, -With furbish'd arms and new supplies of men -Began a fresh assault. -Duncan. Dismay'd not this -Our captains, Macbeth and Banquo? -Sergeant. Yes; -As sparrows eagles, or the hare the lion. -If I say sooth, I must report they were -As cannons overcharged with double cracks, so they -Doubly redoubled strokes upon the foe: -Except they meant to bathe in reeking wounds, -Or memorise another Golgotha, -I cannot tell. -But I am faint, my gashes cry for help. -Duncan. So well thy words become thee as thy wounds; -They smack of honour both. Go get him surgeons. -[Exit Sergeant, attended] -Who comes here? -[Enter ROSS] - -Malcolm. The worthy thane of Ross. -Lennox. What a haste looks through his eyes! So should he look -That seems to speak things strange. -Ross. God save the king! -Duncan. Whence camest thou, worthy thane? -Ross. From Fife, great king; -Where the Norweyan banners flout the sky -And fan our people cold. Norway himself, -With terrible numbers, -Assisted by that most disloyal traitor -The thane of Cawdor, began a dismal conflict; -Till that Bellona's bridegroom, lapp'd in proof, -Confronted him with self-comparisons, -Point against point rebellious, arm 'gainst arm. -Curbing his lavish spirit: and, to conclude, -The victory fell on us. -Duncan. Great happiness! -Ross. That now -Sweno, the Norways' king, craves composition: -Nor would we deign him burial of his men -Till he disbursed at Saint Colme's inch -Ten thousand dollars to our general use. -Duncan. No more that thane of Cawdor shall deceive -Our bosom interest: go pronounce his present death, -And with his former title greet Macbeth. -Ross. I'll see it done. -Duncan. What he hath lost noble Macbeth hath won. -[Exeunt] - ---- -Act I, Scene - -A heath near Forres. - ---- -[Thunder. Enter the three Witches] - -First Witch. Where hast thou been, sister? -Second Witch. Killing swine. -Third Witch. Sister, where thou? -First Witch. A sailor's wife had chestnuts in her lap, -And munch'd, and munch'd, and munch'd:- -'Give me,' quoth I: -'Aroint thee, witch!' the rump-fed ronyon cries. -Her husband's to Aleppo gone, master o' the Tiger: -But in a sieve I'll thither sail, -And, like a rat without a tail, -I'll do, I'll do, and I'll do. -Second Witch. I'll give thee a wind. -First Witch. Thou'rt kind. -Third Witch. And I another. -First Witch. I myself have all the other, -And the very ports they blow, -All the quarters that they know -I' the shipman's card. -I will drain him dry as hay: -Sleep shall neither night nor day -Hang upon his pent-house lid; -He shall live a man forbid: -Weary se'nnights nine times nine -Shall he dwindle, peak and pine: -Though his bark cannot be lost, -Yet it shall be tempest-tost. -Look what I have. -Second Witch. Show me, show me. -First Witch. Here I have a pilot's thumb, -Wreck'd as homeward he did come. -[Drum within] - -Third Witch. A drum, a drum! -Macbeth doth come. -All. The weird sisters, hand in hand, -Posters of the sea and land, -Thus do go about, about: -Thrice to thine and thrice to mine -And thrice again, to make up nine. -Peace! the charm's wound up. -[Enter MACBETH and BANQUO] - -Macbeth. So foul and fair a day I have not seen. -Banquo. How far is't call'd to Forres? What are these -So wither'd and so wild in their attire, -That look not like the inhabitants o' the earth, -And yet are on't? Live you? or are you aught -That man may question? You seem to understand me, -By each at once her chappy finger laying -Upon her skinny lips: you should be women, -And yet your beards forbid me to interpret -That you are so. -Macbeth. Speak, if you can: what are you? -First Witch. All hail, Macbeth! hail to thee, thane of Glamis! -Second Witch. All hail, Macbeth, hail to thee, thane of Cawdor! -Third Witch. All hail, Macbeth, thou shalt be king hereafter! -Banquo. Good sir, why do you start; and seem to fear -Things that do sound so fair? I' the name of truth, -Are ye fantastical, or that indeed -Which outwardly ye show? My noble partner -You greet with present grace and great prediction -Of noble having and of royal hope, -That he seems rapt withal: to me you speak not. -If you can look into the seeds of time, -And say which grain will grow and which will not, -Speak then to me, who neither beg nor fear -Your favours nor your hate. -First Witch. Hail! -Second Witch. Hail! -Third Witch. Hail! -First Witch. Lesser than Macbeth, and greater. -Second Witch. Not so happy, yet much happier. -Third Witch. Thou shalt get kings, though thou be none: -So all hail, Macbeth and Banquo! -First Witch. Banquo and Macbeth, all hail! -Macbeth. Stay, you imperfect speakers, tell me more: -By Sinel's death I know I am thane of Glamis; -But how of Cawdor? the thane of Cawdor lives, -A prosperous gentleman; and to be king -Stands not within the prospect of belief, -No more than to be Cawdor. Say from whence -You owe this strange intelligence? or why -Upon this blasted heath you stop our way -With such prophetic greeting? Speak, I charge you. -[Witches vanish] - -Banquo. The earth hath bubbles, as the water has, -And these are of them. Whither are they vanish'd? -Macbeth. Into the air; and what seem'd corporal melted -As breath into the wind. Would they had stay'd! -Banquo. Were such things here as we do speak about? -Or have we eaten on the insane root -That takes the reason prisoner? -Macbeth. Your children shall be kings. -Banquo. You shall be king. -Macbeth. And thane of Cawdor too: went it not so? -Banquo. To the selfsame tune and words. Who's here? -[Enter ROSS and ANGUS] - -Ross. The king hath happily received, Macbeth, -The news of thy success; and when he reads -Thy personal venture in the rebels' fight, -His wonders and his praises do contend -Which should be thine or his: silenced with that, -In viewing o'er the rest o' the selfsame day, -He finds thee in the stout Norweyan ranks, -Nothing afeard of what thyself didst make, -Strange images of death. As thick as hail -Came post with post; and every one did bear -Thy praises in his kingdom's great defence, -And pour'd them down before him. -Angus. We are sent -To give thee from our royal master thanks; -Only to herald thee into his sight, -Not pay thee. -Ross. And, for an earnest of a greater honour, -He bade me, from him, call thee thane of Cawdor: -In which addition, hail, most worthy thane! -For it is thine. -Banquo. What, can the devil speak true? -Macbeth. The thane of Cawdor lives: why do you dress me -In borrow'd robes? -Angus. Who was the thane lives yet; -But under heavy judgment bears that life -Which he deserves to lose. Whether he was combined -With those of Norway, or did line the rebel -With hidden help and vantage, or that with both -He labour'd in his country's wreck, I know not; -But treasons capital, confess'd and proved, -Have overthrown him. -Macbeth. [Aside] Glamis, and thane of Cawdor! -The greatest is behind. -[To ROSS and ANGUS] -Thanks for your pains. -[To BANQUO] -Do you not hope your children shall be kings, -When those that gave the thane of Cawdor to me -Promised no less to them? -Banquo. That trusted home -Might yet enkindle you unto the crown, -Besides the thane of Cawdor. But 'tis strange: -And oftentimes, to win us to our harm, -The instruments of darkness tell us truths, -Win us with honest trifles, to betray's -In deepest consequence. -Cousins, a word, I pray you. -Macbeth. [Aside]. Two truths are told, -As happy prologues to the swelling act -Of the imperial theme.-I thank you, gentlemen. -[Aside] This supernatural soliciting] -Cannot be ill, cannot be good: if ill, -Why hath it given me earnest of success, -Commencing in a truth? I am thane of Cawdor: -If good, why do I yield to that suggestion -Whose horrid image doth unfix my hair -And make my seated heart knock at my ribs, -Against the use of nature? Present fears -Are less than horrible imaginings: -My thought, whose murder yet is but fantastical, -Shakes so my single state of man that function -Is smother'd in surmise, and nothing is -But what is not. -Banquo. Look, how our partner's rapt. -Macbeth. [Aside] If chance will have me king, why, chance may crown me, -Without my stir. -Banquo. New horrors come upon him, -Like our strange garments, cleave not to their mould -But with the aid of use. -Macbeth. [Aside] Come what come may, -Time and the hour runs through the roughest day. -Banquo. Worthy Macbeth, we stay upon your leisure. -Macbeth. Give me your favour: my dull brain was wrought -With things forgotten. Kind gentlemen, your pains -Are register'd where every day I turn -The leaf to read them. Let us toward the king. -Think upon what hath chanced, and, at more time, -The interim having weigh'd it, let us speak -Our free hearts each to other. -Banquo. Very gladly. -Macbeth. Till then, enough. Come, friends. diff --git a/cbor/src/test/resources/data/macbeth-snippet.txt b/cbor/src/test/resources/data/macbeth-snippet.txt deleted file mode 100644 index 33843ed37..000000000 --- a/cbor/src/test/resources/data/macbeth-snippet.txt +++ /dev/null @@ -1,296 +0,0 @@ -The Tragedy of Macbeth, often shortened to Macbeth, is a tragedy by William Shakespeare, estimated to have been first performed in 1606 ---- -Act I, Scene - -A desert place. ---- - -First Witch. When shall we three meet again -In thunder, lightning, or in rain? -Second Witch. When the hurlyburly's done, -When the battle's lost and won. -Third Witch. That will be ere the set of sun. -First Witch. Where the place? -Second Witch. Upon the heath. -Third Witch. There to meet with Macbeth. -First Witch. I come, Graymalkin! -Second Witch. Paddock calls. -Third Witch. Anon. -All. Fair is foul, and foul is fair: -Hover through the fog and filthy air. - ---- -Act I, Scene - -A camp near Forres. ---- - -Duncan. What bloody man is that? He can report, -As seemeth by his plight, of the revolt -The newest state. -Malcolm. This is the sergeant -Who like a good and hardy soldier fought -'Gainst my captivity. Hail, brave friend! -Say to the king the knowledge of the broil -As thou didst leave it. -Sergeant. Doubtful it stood; -As two spent swimmers, that do cling together -And choke their art. The merciless Macdonwald- -Worthy to be a rebel, for to that -The multiplying villanies of nature -Do swarm upon him-from the western isles -Of kerns and gallowglasses is supplied; -And fortune, on his damned quarrel smiling, -Show'd like a rebel's whore: but all's too weak: -For brave Macbeth-well he deserves that name- -Disdaining fortune, with his brandish'd steel, -Which smoked with bloody execution, -Like valour's minion carved out his passage -Till he faced the slave; -Which ne'er shook hands, nor bade farewell to him, -Till he unseam'd him from the nave to the chaps, -And fix'd his head upon our battlements. -Duncan. O valiant cousin! worthy gentleman! -Sergeant. As whence the sun 'gins his reflection -Shipwrecking storms and direful thunders break, -So from that spring whence comfort seem'd to come -Discomfort swells. Mark, king of Scotland, mark: -No sooner justice had with valour arm'd -Compell'd these skipping kerns to trust their heels, -But the Norweyan lord surveying vantage, -With furbish'd arms and new supplies of men -Began a fresh assault. -Duncan. Dismay'd not this -Our captains, Macbeth and Banquo? -Sergeant. Yes; -As sparrows eagles, or the hare the lion. -If I say sooth, I must report they were -As cannons overcharged with double cracks, so they -Doubly redoubled strokes upon the foe: -Except they meant to bathe in reeking wounds, -Or memorise another Golgotha, -I cannot tell. -But I am faint, my gashes cry for help. -Duncan. So well thy words become thee as thy wounds; -They smack of honour both. Go get him surgeons. -[Exit Sergeant, attended] -Who comes here? -[Enter ROSS] - -Malcolm. The worthy thane of Ross. -Lennox. What a haste looks through his eyes! So should he look -That seems to speak things strange. -Ross. God save the king! -Duncan. Whence camest thou, worthy thane? -Ross. From Fife, great king; -Where the Norweyan banners flout the sky -And fan our people cold. Norway himself, -With terrible numbers, -Assisted by that most disloyal traitor -The thane of Cawdor, began a dismal conflict; -Till that Bellona's bridegroom, lapp'd in proof, -Confronted him with self-comparisons, -Point against point rebellious, arm 'gainst arm. -Curbing his lavish spirit: and, to conclude, -The victory fell on us. -Duncan. Great happiness! -Ross. That now -Sweno, the Norways' king, craves composition: -Nor would we deign him burial of his men -Till he disbursed at Saint Colme's inch -Ten thousand dollars to our general use. -Duncan. No more that thane of Cawdor shall deceive -Our bosom interest: go pronounce his present death, -And with his former title greet Macbeth. -Ross. I'll see it done. -Duncan. What he hath lost noble Macbeth hath won. -[Exeunt] - ---- -Act I, Scene - -A heath near Forres. - ---- -[Thunder. Enter the three Witches] - -First Witch. Where hast thou been, sister? -Second Witch. Killing swine. -Third Witch. Sister, where thou? -First Witch. A sailor's wife had chestnuts in her lap, -And munch'd, and munch'd, and munch'd:- -'Give me,' quoth I: -'Aroint thee, witch!' the rump-fed ronyon cries. -Her husband's to Aleppo gone, master o' the Tiger: -But in a sieve I'll thither sail, -And, like a rat without a tail, -I'll do, I'll do, and I'll do. -Second Witch. I'll give thee a wind. -First Witch. Thou'rt kind. -Third Witch. And I another. -First Witch. I myself have all the other, -And the very ports they blow, -All the quarters that they know -I' the shipman's card. -I will drain him dry as hay: -Sleep shall neither night nor day -Hang upon his pent-house lid; -He shall live a man forbid: -Weary se'nnights nine times nine -Shall he dwindle, peak and pine: -Though his bark cannot be lost, -Yet it shall be tempest-tost. -Look what I have. -Second Witch. Show me, show me. -First Witch. Here I have a pilot's thumb, -Wreck'd as homeward he did come. -[Drum within] - -Third Witch. A drum, a drum! -Macbeth doth come. -All. The weird sisters, hand in hand, -Posters of the sea and land, -Thus do go about, about: -Thrice to thine and thrice to mine -And thrice again, to make up nine. -Peace! the charm's wound up. -[Enter MACBETH and BANQUO] - -Macbeth. So foul and fair a day I have not seen. -Banquo. How far is't call'd to Forres? What are these -So wither'd and so wild in their attire, -That look not like the inhabitants o' the earth, -And yet are on't? Live you? or are you aught -That man may question? You seem to understand me, -By each at once her chappy finger laying -Upon her skinny lips: you should be women, -And yet your beards forbid me to interpret -That you are so. -Macbeth. Speak, if you can: what are you? -First Witch. All hail, Macbeth! hail to thee, thane of Glamis! -Second Witch. All hail, Macbeth, hail to thee, thane of Cawdor! -Third Witch. All hail, Macbeth, thou shalt be king hereafter! -Banquo. Good sir, why do you start; and seem to fear -Things that do sound so fair? I' the name of truth, -Are ye fantastical, or that indeed -Which outwardly ye show? My noble partner -You greet with present grace and great prediction -Of noble having and of royal hope, -That he seems rapt withal: to me you speak not. -If you can look into the seeds of time, -And say which grain will grow and which will not, -Speak then to me, who neither beg nor fear -Your favours nor your hate. -First Witch. Hail! -Second Witch. Hail! -Third Witch. Hail! -First Witch. Lesser than Macbeth, and greater. -Second Witch. Not so happy, yet much happier. -Third Witch. Thou shalt get kings, though thou be none: -So all hail, Macbeth and Banquo! -First Witch. Banquo and Macbeth, all hail! -Macbeth. Stay, you imperfect speakers, tell me more: -By Sinel's death I know I am thane of Glamis; -But how of Cawdor? the thane of Cawdor lives, -A prosperous gentleman; and to be king -Stands not within the prospect of belief, -No more than to be Cawdor. Say from whence -You owe this strange intelligence? or why -Upon this blasted heath you stop our way -With such prophetic greeting? Speak, I charge you. -[Witches vanish] - -Banquo. The earth hath bubbles, as the water has, -And these are of them. Whither are they vanish'd? -Macbeth. Into the air; and what seem'd corporal melted -As breath into the wind. Would they had stay'd! -Banquo. Were such things here as we do speak about? -Or have we eaten on the insane root -That takes the reason prisoner? -Macbeth. Your children shall be kings. -Banquo. You shall be king. -Macbeth. And thane of Cawdor too: went it not so? -Banquo. To the selfsame tune and words. Who's here? -[Enter ROSS and ANGUS] - -Ross. The king hath happily received, Macbeth, -The news of thy success; and when he reads -Thy personal venture in the rebels' fight, -His wonders and his praises do contend -Which should be thine or his: silenced with that, -In viewing o'er the rest o' the selfsame day, -He finds thee in the stout Norweyan ranks, -Nothing afeard of what thyself didst make, -Strange images of death. As thick as hail -Came post with post; and every one did bear -Thy praises in his kingdom's great defence, -And pour'd them down before him. -Angus. We are sent -To give thee from our royal master thanks; -Only to herald thee into his sight, -Not pay thee. -Ross. And, for an earnest of a greater honour, -He bade me, from him, call thee thane of Cawdor: -In which addition, hail, most worthy thane! -For it is thine. -Banquo. What, can the devil speak true? -Macbeth. The thane of Cawdor lives: why do you dress me -In borrow'd robes? -Angus. Who was the thane lives yet; -But under heavy judgment bears that life -Which he deserves to lose. Whether he was combined -With those of Norway, or did line the rebel -With hidden help and vantage, or that with both -He labour'd in his country's wreck, I know not; -But treasons capital, confess'd and proved, -Have overthrown him. -Macbeth. [Aside] Glamis, and thane of Cawdor! -The greatest is behind. -[To ROSS and ANGUS] -Thanks for your pains. -[To BANQUO] -Do you not hope your children shall be kings, -When those that gave the thane of Cawdor to me -Promised no less to them? -Banquo. That trusted home -Might yet enkindle you unto the crown, -Besides the thane of Cawdor. But 'tis strange: -And oftentimes, to win us to our harm, -The instruments of darkness tell us truths, -Win us with honest trifles, to betray's -In deepest consequence. -Cousins, a word, I pray you. -Macbeth. [Aside]. Two truths are told, -As happy prologues to the swelling act -Of the imperial theme.-I thank you, gentlemen. -[Aside] This supernatural soliciting] -Cannot be ill, cannot be good: if ill, -Why hath it given me earnest of success, -Commencing in a truth? I am thane of Cawdor: -If good, why do I yield to that suggestion -Whose horrid image doth unfix my hair -And make my seated heart knock at my ribs, -Against the use of nature? Present fears -Are less than horrible imaginings: -My thought, whose murder yet is but fantastical, -Shakes so my single state of man that function -Is smother'd in surmise, and nothing is -But what is not. -Banquo. Look, how our partner's rapt. -Macbeth. [Aside] If chance will have me king, why, chance may crown me, -Without my stir. -Banquo. New horrors come upon him, -Like our strange garments, cleave not to their mould -But with the aid of use. -Macbeth. [Aside] Come what come may, -Time and the hour runs through the roughest day. -Banquo. Worthy Macbeth, we stay upon your leisure. -Macbeth. Give me your favour: my dull brain was wrought -With things forgotten. Kind gentlemen, your pains -Are register'd where every day I turn -The leaf to read them. Let us toward the king. -Think upon what hath chanced, and, at more time, -The interim having weigh'd it, let us speak -Our free hearts each to other. -Banquo. Very gladly. -Macbeth. Till then, enough. Come, friends. From ebaae4bd2a1cb9b6275dc71cc66459ea9a4ea3c2 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 11 May 2026 19:30:58 -0700 Subject: [PATCH 2/3] Add release notes --- release-notes/CREDITS-2.x | 5 ++++- release-notes/VERSION-2.x | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 453530011..f4c3091b2 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -386,9 +386,12 @@ Manuel Sugawara (@sugmanue) (2.19.0) * Contributed fix for #616: CBOR text gets truncated on decoding (2.19.3) - * Conribued fix for #640: (cbor) CBOR throws ArrayIndexOutOfBoundsException + * Contributed fix for #640: (cbor) CBOR throws ArrayIndexOutOfBoundsException with long ASCII text (2.20.2) + * Contributed #691: (cbor) Add parameterized tests covering all ASCII-optimization + exit paths in CBORParser + (2.21.4) Josh Curry (@seadbrane) * Reported, contributed fix for #571: Unable to deserialize a pojo with IonStruct diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index b3d7e713e..dffa8c699 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -14,9 +14,14 @@ Active maintainers: === Releases === ------------------------------------------------------------------------ +2.21.4 (not yet released) + +#691: (cbor) Add parameterized tests covering all ASCII-optimization exit paths in CBORParser + (contributed by Manuel S) + 2.21.3 (28-Apr-2026) -#686: `CBORParser._finishLongTextAscii` returns negative length when `TextBuffer` +#686: (cbor) `CBORParser._finishLongTextAscii` returns negative length when `TextBuffer` segment > I/O buffer, leaving non-ASCII byte unconsumed (fixed by Halil İbrahim Åž) From b9e8a4deee752ddc9f8a63fa7169eb0b65140e35 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 11 May 2026 19:34:59 -0700 Subject: [PATCH 3/3] Minor test cleanup --- .../cbor/parse/AsciiTextCornerCasesTest.java | 47 +++++++++++++++++++ .../parse/TruncatedLongAsciiTextTest.java | 26 +++++----- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java index 3385dea9c..4f470996c 100644 --- a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/AsciiTextCornerCasesTest.java @@ -1,11 +1,14 @@ package com.fasterxml.jackson.dataformat.cbor.parse; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -164,6 +167,50 @@ public void testRepeatedParsesWithBufferGrowth(int asciiPrefix, String flavor) t } } + /** + * Targeted test for the top-of-loop exit in _finishChunkedTextAscii: + * the final ASCII byte of the chunk sits exactly at the I/O buffer + * boundary so that, on the iteration after the chunk's bytes are fully + * consumed, both _inputPtr >= _chunkEnd and _chunkLeft == 0 hold + * simultaneously and the method must return without peeking past the + * window (the break byte 0xFF lives in the next buffer fill). + */ + @Test + public void testChunkedTextEndsAtIOBufferBoundary() throws Exception + { + // Default CBORParser I/O buffer size is 8000 bytes. + // Layout (total = 8001 bytes): + // [0] 0x7F indefinite-length text + // [1..3] 0x79 HH LL chunk header (2-byte length) + // [4..7999] payload exactly fills the first I/O read + // [8000] 0xFF break byte (next I/O read) + final int payloadLen = IO_BUF - 4; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(0x7F); + bos.write(0x79); + bos.write((payloadLen >> 8) & 0xFF); + bos.write(payloadLen & 0xFF); + byte[] payload = new byte[payloadLen]; + Arrays.fill(payload, (byte) 'A'); + bos.write(payload); + bos.write(0xFF); + byte[] cbor = bos.toByteArray(); + assertEquals(IO_BUF + 1, cbor.length); + + CBORFactory f = cborFactory(); + // Plain ByteArrayInputStream: first read fills exactly IO_BUF bytes, + // setting _chunkEnd == _inputEnd == IO_BUF and _chunkLeft == 0. + try (CBORParser p = cborParser(f, new ByteArrayInputStream(cbor))) { + assertEquals(JsonToken.VALUE_STRING, p.nextToken()); + String text = p.getText(); + assertEquals(payloadLen, text.length()); + for (int i = 0; i < payloadLen; i++) { + assertEquals('A', text.charAt(i), + "mismatch at index " + i); + } + } + } + private String buildTestString(int asciiPrefix, String flavor) { if ("pure_ascii".equals(flavor)) { return generateLongAsciiString(asciiPrefix); diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java index ec34e916d..fa0e7f2b5 100644 --- a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/TruncatedLongAsciiTextTest.java @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Test; import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.core.io.JsonEOFException; import com.fasterxml.jackson.dataformat.cbor.CBORFactory; import com.fasterxml.jackson.dataformat.cbor.CBORParser; import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; @@ -16,16 +16,15 @@ import static org.junit.jupiter.api.Assertions.*; /** - * Test for missing setCurrentLength on the early-return path in _finishLongTextAscii - * when _tryToLoadToHaveAtLeast returns false (stream ends prematurely). + * Tests guarding the early-return path in _finishLongTextAscii when + * _tryToLoadToHaveAtLeast returns false (stream ends prematurely). * - * The bug exists in the code (outPtr > 0 but setCurrentLength not called), but in - * practice it's masked because the caller _finishLongText then tries to read the - * remaining bytes via _nextByte() which throws on EOF before the corrupted TextBuffer - * is ever converted to a String. - * - * These tests document the behavior and verify correctness on both truncated and - * valid long ASCII input via throttled streams. + * That path now syncs the TextBuffer via setCurrentLength(outPtr) so the buffer + * never holds partially-written state that could be exposed as a String. In + * practice EOF is reported by the caller (_finishLongText reads remaining bytes + * via _nextByte() and throws on EOF) before any partial text could be + * materialized, but the sync makes the invariant local to _finishLongTextAscii + * rather than relying on caller behavior. */ public class TruncatedLongAsciiTextTest extends CBORTestBase { @@ -44,7 +43,12 @@ public void testTruncatedAsciiThrowsCleanly() throws Exception try (CBORParser p = cborParser(f, new ThrottledInputStream(cbor, 2000))) { assertEquals(JsonToken.VALUE_STRING, p.nextToken()); - assertThrows(StreamReadException.class, () -> p.getText()); + JsonEOFException e = assertThrows(JsonEOFException.class, () -> p.getText()); + // Must surface as EOF rather than silently returning a partial String; + // also guards against a regression where the truncated TextBuffer is + // converted to a String before EOF is detected. + assertTrue(e.getMessage().contains("end-of-input"), + "Unexpected message: " + e.getMessage()); } }