|
| 1 | +# Issues to address |
| 2 | + |
| 3 | +## msgpack-jackson3-specific |
| 4 | + |
| 5 | +### 1. `isClosed()` always returns false |
| 6 | + |
| 7 | +**File:** `msgpack-jackson3/.../MessagePackGenerator.java` (close method) |
| 8 | + |
| 9 | +`close()` cannot call `super.close()` because `GeneratorBase.close()` in Jackson 3 |
| 10 | +closes the underlying output stream as a side effect, breaking tests that disable |
| 11 | +`AUTO_CLOSE_TARGET`. As a result `isClosed()` always returns false and callers can |
| 12 | +continue writing into a closed generator without getting the standard exception. |
| 13 | + |
| 14 | +### 2. `MessagePackFactory.snapshot()` returns `this` — FIXED |
| 15 | + |
| 16 | +**File:** `msgpack-jackson3/.../MessagePackFactory.java` |
| 17 | + |
| 18 | +Fixed: `snapshot()` now delegates to `copy()`, and `rebuild()` is implemented via `MessagePackFactoryBuilder`. |
| 19 | + |
| 20 | +### 3. Build: `msgpack-jackson3` fails to compile locally on Java < 17 |
| 21 | + |
| 22 | +`msgpack-jackson3` is in the root aggregate unconditionally. The CI works around |
| 23 | +this with a bash version check, but a developer running `./sbt test` locally on |
| 24 | +Java 8 or 11 gets a hard compilation failure. A cleaner build-level solution |
| 25 | +(conditional aggregate, toolchain support, or a separate profile) is needed. |
| 26 | + |
| 27 | +### 4. `MessagePackGenerator.streamWriteContext()` returns null |
| 28 | + |
| 29 | +**File:** `msgpack-jackson3/.../MessagePackGenerator.java` (streamWriteContext method) |
| 30 | + |
| 31 | +`streamWriteContext()` returns `null`, bypassing Jackson's standard write context |
| 32 | +management. This can cause NPEs in Jackson code paths that use the context for path |
| 33 | +tracking in error messages or certain serialization features. Fixing it properly |
| 34 | +requires integrating with Jackson 3's `TokenStreamContext` / `_streamWriteContext` |
| 35 | +managed by `GeneratorBase`, which needs investigation. |
| 36 | + |
| 37 | +### 5. `writeString(Reader, int)` len=-1 implementation allocates an extra copy |
| 38 | + |
| 39 | +**File:** `msgpack-jackson3/.../MessagePackGenerator.java` (writeString(Reader, int)) |
| 40 | + |
| 41 | +The len=-1 path buffers into a `StringBuilder` then copies to a `char[]`. Using a |
| 42 | +`CharArrayWriter` would avoid the intermediate allocation. |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## msgpack-jackson pre-existing issues |
| 47 | + |
| 48 | +These issues were identified during review of msgpack-jackson3 and confirmed to exist |
| 49 | +identically in msgpack-jackson. They should be addressed in both modules together. |
| 50 | + |
| 51 | +## 1. `MessagePackParser`: Same byte-array input skips unpacker reset |
| 52 | + |
| 53 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java:130` |
| 54 | + |
| 55 | +When `AUTO_CLOSE_SOURCE` is disabled and the same byte-array instance is parsed more |
| 56 | +than once (e.g. reused buffer), the condition `messageUnpackerTuple.first() != src` |
| 57 | +is false, so the unpacker is not reset. The second parse continues from where the first |
| 58 | +left off instead of from the beginning. |
| 59 | + |
| 60 | +## 2. `MessagePackParser`: ThreadLocal retains last byte-array payload per thread |
| 61 | + |
| 62 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java:135` |
| 63 | + |
| 64 | +`messageUnpackerHolder` is never cleared on parser close. For byte-array inputs this |
| 65 | +retains the entire last parsed payload for each thread in a pool indefinitely, which |
| 66 | +can cause unbounded memory retention after large messages. |
| 67 | + |
| 68 | +## 3. `MessagePackGenerator`: `close()` does not call `super.close()` |
| 69 | + |
| 70 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` (close method) |
| 71 | + |
| 72 | +The `close()` override never delegates to `GeneratorBase.close()`, so `isClosed()` |
| 73 | +remains false after close. Callers can continue writing into a closed generator |
| 74 | +instead of getting the standard closed-generator exception. |
| 75 | + |
| 76 | +## 4. `MessagePackGenerator`: `writeString(Reader, int)` crashes on length -1 |
| 77 | + |
| 78 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` (writeString(Reader, int)) |
| 79 | + |
| 80 | +`new char[len]` throws `NegativeArraySizeException` when `len` is -1, which is a |
| 81 | +valid Jackson API usage meaning "unknown length, read until EOF". |
| 82 | + |
| 83 | +## 5. `MessagePackGenerator`: `writeNumber(String)` tries `Double.parseDouble` before `BigInteger` |
| 84 | + |
| 85 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java:699` |
| 86 | + |
| 87 | +Integer strings outside the `long` range are serialized as floating-point values, |
| 88 | +losing precision, even though MessagePack can encode big integers exactly. The order |
| 89 | +should try integer parsing first. |
| 90 | + |
| 91 | +## 6. `MessagePackGenerator`: Closing a container leaves stale `currentState` |
| 92 | + |
| 93 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` (writeEndArray/writeEndObject) |
| 94 | + |
| 95 | +After `flush()` clears `nodes`, any subsequent root-level value written with the |
| 96 | +same generator is treated as if inside the old container, which can corrupt output. |
| 97 | + |
| 98 | +## 7. `MessagePackSerializedString`: Most interface methods are stubs |
| 99 | + |
| 100 | +**File:** `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java:70` |
| 101 | + |
| 102 | +Most `SerializableString` methods return 0 or do nothing. Any Jackson code path |
| 103 | +that calls these methods (e.g. for length or byte-copy operations) will silently |
| 104 | +produce incorrect results. |
| 105 | + |
| 106 | +## 8. `MessagePackGenerator`: `getBytesIfAscii` writes to wrong index when offset > 0 |
| 107 | + |
| 108 | +**Files:** |
| 109 | +- `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java:474` |
| 110 | +- `msgpack-jackson3/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` — FIXED |
| 111 | + |
| 112 | +`bytes[i] = (byte) c` should be `bytes[i - offset] = (byte) c`. When offset > 0, `i` |
| 113 | +starts above 0 but `bytes` is length `len`, so it throws `ArrayIndexOutOfBoundsException`. |
| 114 | +Fixed in msgpack-jackson3; needs the same fix in msgpack-jackson. |
| 115 | + |
| 116 | +**Practical impact:** Low. `writeString(char[], offset, len)` is a low-level Jackson |
| 117 | +streaming API used by Jackson's own internals and performance-sensitive custom serializers, |
| 118 | +not by typical application code. Normal users call `writeString(String)` instead. |
| 119 | + |
| 120 | +## 9. `MessagePackGenerator`: `writeByteArrayTextValue` ASCII path ignores offset |
| 121 | + |
| 122 | +**Files:** |
| 123 | +- `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java:512` |
| 124 | +- `msgpack-jackson3/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` — FIXED |
| 125 | + |
| 126 | +`addValueNode(new AsciiCharString(text))` stores the entire backing array instead of |
| 127 | +the requested slice `[offset, offset+len)`. Callers such as `writeRawUTF8String` and |
| 128 | +`writeUTF8String` with non-zero offsets will serialize garbage bytes. |
| 129 | +Fixed in msgpack-jackson3 using `System.arraycopy`; needs the same fix in msgpack-jackson. |
| 130 | + |
| 131 | +**Practical impact:** Low. `writeUTF8String(byte[], offset, len)` is a low-level API |
| 132 | +called by Jackson's streaming infrastructure or custom serializers working with raw |
| 133 | +byte buffers. Typical application code goes through ObjectMapper, which always passes |
| 134 | +offset=0 for plain byte arrays. |
| 135 | + |
| 136 | +## 10. `MessagePackGenerator`: ByteBuffer serialization ignores `position()` |
| 137 | + |
| 138 | +**Files:** |
| 139 | +- `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java:369` |
| 140 | +- `msgpack-jackson3/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java` — FIXED |
| 141 | + |
| 142 | +`writePayload(bb.array(), bb.arrayOffset(), len)` ignores `bb.position()`. For any |
| 143 | +ByteBuffer with a non-zero position (e.g. from `ByteBuffer.wrap(data, offset, len)` or |
| 144 | +after reads), this serializes bytes starting at the wrong offset. |
| 145 | +Fixed in msgpack-jackson3 using `bb.arrayOffset() + bb.position()`; needs the same fix in msgpack-jackson. |
| 146 | + |
| 147 | +**Practical impact:** Moderate. This is the most realistic end-user scenario: a POJO |
| 148 | +with a `ByteBuffer` field that was sliced or partially consumed will silently produce |
| 149 | +corrupt serialized output. No exception is thrown. |
| 150 | + |
0 commit comments