From fe0f292cecceaf78d070d6f385c7416aba39cfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Mar 2026 14:13:03 +0800 Subject: [PATCH] FFstrbuf: adds new `ffStrbufDecodeHexEscapeSequences` --- src/common/FFstrbuf.h | 2 ++ src/common/impl/FFstrbuf.c | 42 +++++++++++++++++++++++++++++++++ src/common/stringUtils.h | 17 +++++++++++++ src/detection/disk/disk_linux.c | 16 +------------ tests/strbuf.c | 23 ++++++++++++++++++ 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index 6c194687f..ba6f42518 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -628,4 +628,6 @@ static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator); } +bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); + #define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy))) diff --git a/src/common/impl/FFstrbuf.c b/src/common/impl/FFstrbuf.c index 09e79b355..5df26f7e0 100644 --- a/src/common/impl/FFstrbuf.c +++ b/src/common/impl/FFstrbuf.c @@ -1,5 +1,6 @@ #include "common/FFstrbuf.h" #include "common/mallocHelper.h" +#include "common/stringUtils.h" #include #include @@ -915,3 +916,44 @@ bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLeng return false; } + +bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf) +{ + assert(strbuf); + + if (strbuf->length < 4) + return false; + + // Static string must be converted first. + assert(strbuf->allocated > 0); + + bool changed = false; + uint32_t read = 0; + uint32_t write = 0; + + while (read < strbuf->length) + { + if ( + read + 3 < strbuf->length && + strbuf->chars[read] == '\\' && + strbuf->chars[read + 1] == 'x' + ) + { + int8_t hi = ffHexCharToInt(strbuf->chars[read + 2]); + int8_t lo = ffHexCharToInt(strbuf->chars[read + 3]); + if (hi >= 0 && lo >= 0) + { + strbuf->chars[write++] = (char) ((hi << 4) | lo); + read += 4; + changed = true; + continue; + } + } + + strbuf->chars[write++] = strbuf->chars[read++]; + } + + strbuf->length = write; + strbuf->chars[write] = '\0'; + return changed; +} diff --git a/src/common/stringUtils.h b/src/common/stringUtils.h index 9a3f43712..3afbe6ec3 100644 --- a/src/common/stringUtils.h +++ b/src/common/stringUtils.h @@ -80,6 +80,23 @@ static inline bool ffCharIsDigit(char c) return '0' <= c && c <= '9'; } +static inline bool ffCharIsHexDigit(char c) +{ + return ffCharIsDigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); +} + +static inline int8_t ffHexCharToInt(char c) +{ + if (ffCharIsDigit(c)) + return (int8_t) (c - '0'); + else if ('a' <= c && c <= 'f') + return (int8_t) (c - 'a' + 10); + else if ('A' <= c && c <= 'F') + return (int8_t) (c - 'A' + 10); + else + return -1; +} + // Copies at most (dstBufSiz - 1) bytes from src to dst; dst is always null-terminated static inline char* ffStrCopy(char* __restrict__ dst, const char* __restrict__ src, size_t dstBufSiz) { diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 5bdf83644..70474710f 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -140,21 +140,7 @@ static void detectName(FFDisk* disk) if (disk->name.length == 0) return; - // Basic\x20data\x20partition - for (uint32_t i = ffStrbufFirstIndexS(&disk->name, "\\x"); - i != disk->name.length; - i = ffStrbufNextIndexS(&disk->name, i + 1, "\\x")) - { - uint32_t len = (uint32_t) strlen("\\x20"); - if (disk->name.length >= len) - { - char bak = disk->name.chars[i + len]; - disk->name.chars[i + len] = '\0'; - disk->name.chars[i] = (char) strtoul(&disk->name.chars[i + 2], NULL, 16); - ffStrbufRemoveSubstr(&disk->name, i + 1, i + len); - disk->name.chars[i + 1] = bak; - } - } + ffStrbufDecodeHexEscapeSequences(&disk->name); } #ifdef __ANDROID__ diff --git a/tests/strbuf.c b/tests/strbuf.c index aa891698c..69f4ce1c7 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -1035,6 +1035,29 @@ int main(void) ffStrbufDestroy(&strbuf); } + // decode hex escape sequences + { + ffStrbufSetS(&strbuf, "Basic\\x20data\\x20partition"); + VERIFY(ffStrbufDecodeHexEscapeSequences(&strbuf) == true); + VERIFY(ffStrbufEqualS(&strbuf, "Basic data partition")); + + ffStrbufSetS(&strbuf, "\\x41\\x42\\x43"); + VERIFY(ffStrbufDecodeHexEscapeSequences(&strbuf) == true); + VERIFY(ffStrbufEqualS(&strbuf, "ABC")); + + ffStrbufSetS(&strbuf, "abc\\x4"); + VERIFY(ffStrbufDecodeHexEscapeSequences(&strbuf) == false); + VERIFY(ffStrbufEqualS(&strbuf, "abc\\x4")); + + ffStrbufSetS(&strbuf, "abc\\xZZ"); + VERIFY(ffStrbufDecodeHexEscapeSequences(&strbuf) == false); + VERIFY(ffStrbufEqualS(&strbuf, "abc\\xZZ")); + + ffStrbufSetS(&strbuf, "abc\\x2G"); + VERIFY(ffStrbufDecodeHexEscapeSequences(&strbuf) == false); + VERIFY(ffStrbufEqualS(&strbuf, "abc\\x2G")); + } + //setS ffStrbufInitStatic(&strbuf, "STATIC"); ffStrbufSetS(&strbuf, "DYNAMIC");