From dc91ed5e08ea63de95ecb01616aad32f4484b530 Mon Sep 17 00:00:00 2001 From: fox0430 Date: Mon, 13 Apr 2026 16:38:17 +0900 Subject: [PATCH] Fix decodeCString to reject missing null terminator --- async_postgres/pg_protocol.nim | 7 ++++--- async_postgres/pg_replication.nim | 7 +++++-- tests/test_protocol.nim | 10 +++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/async_postgres/pg_protocol.nim b/async_postgres/pg_protocol.nim index ec7497a..4a34647 100644 --- a/async_postgres/pg_protocol.nim +++ b/async_postgres/pg_protocol.nim @@ -329,17 +329,18 @@ proc decodeInt64*(buf: openArray[byte], offset: int): int64 = proc decodeCString*(buf: openArray[byte], offset: int): (string, int) = ## Decode a null-terminated string at the given offset. Returns (string, bytes consumed). - if offset > buf.len: + if offset >= buf.len: raise newException(ProtocolError, "decodeCString: offset past end of buffer") var i = offset while i < buf.len and buf[i] != 0: inc i + if i >= buf.len: + raise newException(ProtocolError, "decodeCString: missing null terminator") let slen = i - offset var s = newString(slen) if slen > 0: copyMem(addr s[0], unsafeAddr buf[offset], slen) - if i < buf.len: - inc i # skip null terminator + inc i # skip null terminator result = (s, i - offset) # Frontend message encoding diff --git a/async_postgres/pg_replication.nim b/async_postgres/pg_replication.nim index 196223a..11ce021 100644 --- a/async_postgres/pg_replication.nim +++ b/async_postgres/pg_replication.nim @@ -230,15 +230,18 @@ proc currentPgTimestamp*(): int64 = proc decodeCStringAt(buf: openArray[byte], offset: int): (string, int) = ## Decode a null-terminated string at offset. Returns (string, next offset). + if offset >= buf.len: + raise newException(ProtocolError, "decodeCStringAt: offset past end of buffer") var i = offset while i < buf.len and buf[i] != 0: inc i + if i >= buf.len: + raise newException(ProtocolError, "decodeCStringAt: missing null terminator") let slen = i - offset var s = newString(slen) if slen > 0: copyMem(addr s[0], unsafeAddr buf[offset], slen) - if i < buf.len: - inc i # skip null + inc i # skip null (s, i) proc decodeTuple(buf: openArray[byte], offset: int): (seq[TupleField], int) = diff --git a/tests/test_protocol.nim b/tests/test_protocol.nim index 712d4f1..e2bc894 100644 --- a/tests/test_protocol.nim +++ b/tests/test_protocol.nim @@ -48,9 +48,8 @@ suite "Byte helpers": test "decodeCString at end of buffer": let buf = @[byte('a'), 0'u8] - let (s, consumed) = decodeCString(buf, 2) - check s == "" - check consumed == 0 + expect(ProtocolError): + discard decodeCString(buf, 2) test "decodeCString offset past end of buffer": let buf = @[byte('a'), 0'u8] @@ -62,6 +61,11 @@ suite "Byte helpers": expect(ProtocolError): discard decodeCString(buf, 1) + test "decodeCString missing null terminator": + let buf = @[byte('h'), byte('i')] + expect(ProtocolError): + discard decodeCString(buf, 0) + suite "Frontend encoding": test "encodeStartup - no type byte, version 3.0": let msg = encodeStartup("testuser", "testdb")