From 890872e8dafeab3080022876d6c601d80624deaa Mon Sep 17 00:00:00 2001 From: wanghongyan Date: Fri, 18 Sep 2026 14:44:06 +0800 Subject: [PATCH v1] add validated RVV pq_getmsgstring candidate Co-authored-by: Ni Jincheng Co-authored-by: Yuansheng --- src/backend/libpq/pqformat.c | 59 ++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index 8b41aa4f1cb..4a1dd5a45c2 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -79,6 +79,13 @@ #include "port/pg_bswap.h" #include "varatt.h" +#if defined(__riscv_vector) && defined(__has_include) +#if __has_include() +#include +#define USE_RISCV_VECTOR_NUL_SCAN +#endif +#endif + /* -------------------------------- * pq_beginmessage - initialize for sending a message @@ -567,6 +574,10 @@ pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes) return p; } +#ifdef USE_RISCV_VECTOR_NUL_SCAN +static int pq_find_nul_rvv(const char *str, int maxlen); +#endif + /* -------------------------------- * pq_getmsgstring - get a null-terminated text string (with conversion) * @@ -587,8 +598,12 @@ pq_getmsgstring(StringInfo msg) * have a trailing null byte. But check we found a null inside the * message. */ +#ifdef USE_RISCV_VECTOR_NUL_SCAN + slen = pq_find_nul_rvv(str, msg->len - msg->cursor); +#else slen = strlen(str); - if (msg->cursor + slen >= msg->len) +#endif + if (slen < 0 || msg->cursor + slen >= msg->len) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid string in message"))); @@ -597,6 +612,42 @@ pq_getmsgstring(StringInfo msg) return pg_client_to_server(str, slen); } +#ifdef USE_RISCV_VECTOR_NUL_SCAN +/* + * Find a null byte without reading beyond the message boundary. Keeping the + * vector length bounded by maxlen avoids the object and page-boundary + * over-read that an unbounded vector strlen implementation could perform. + */ +static int +pq_find_nul_rvv(const char *str, int maxlen) +{ + size_t offset = 0; + size_t remaining; + + if (maxlen <= 0) + return -1; + remaining = maxlen; + + while (remaining > 0) + { + size_t vl = __riscv_vsetvl_e8m8(remaining); + vuint8m8_t bytes; + vbool1_t zeroes; + long position; + + bytes = __riscv_vle8_v_u8m8((const uint8_t *) str + offset, vl); + zeroes = __riscv_vmseq_vx_u8m8_b1(bytes, 0, vl); + position = __riscv_vfirst_m_b1(zeroes, vl); + if (position >= 0) + return (int) (offset + (size_t) position); + offset += vl; + remaining -= vl; + } + + return -1; +} +#endif + /* -------------------------------- * pq_getmsgrawstring - get a null-terminated text string - NO conversion * @@ -616,8 +667,12 @@ pq_getmsgrawstring(StringInfo msg) * have a trailing null byte. But check we found a null inside the * message. */ +#ifdef USE_RISCV_VECTOR_NUL_SCAN + slen = pq_find_nul_rvv(str, msg->len - msg->cursor); +#else slen = strlen(str); - if (msg->cursor + slen >= msg->len) +#endif + if (slen < 0 || msg->cursor + slen >= msg->len) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid string in message"))); -- 2.43.0