String search sees NUL as newline by default.
That is the most intuitive option for binary searches. The behavior can still be changed, as seen in the added example.
This commit is contained in:
parent
e6362c2942
commit
c3a90e9226
7 changed files with 63 additions and 17 deletions
|
|
@ -2901,6 +2901,7 @@ static const RzCmdDescDetailEntry slash_z_Examples_detail_entries[] = {
|
|||
{ .text = "/z", .arg_str = " (ABC*)D li", .comment = "Search the exact string \"(ABC*)D\" but case insensitive." },
|
||||
{ .text = "/z", .arg_str = " \\\\d\\\\sC*\\\\w ri", .comment = "Search the regular expression \"\\d\\sC*\\w\" but case insensitive." },
|
||||
{ .text = "/z", .arg_str = " \"и.{3}м\" ei", .comment = "Search the extended regular expression \"и.{3}м\" but case insensitive." },
|
||||
{ .text = "/z", .arg_str = " \"(*LF).+\" r ascii", .comment = "Search any ascii string with line feed is a newline." },
|
||||
{ 0 },
|
||||
};
|
||||
static const RzCmdDescDetail slash_z_details[] = {
|
||||
|
|
|
|||
|
|
@ -1132,6 +1132,9 @@ commands:
|
|||
- text: "/z"
|
||||
arg_str: " \"и.{3}м\" ei"
|
||||
comment: "Search the extended regular expression \"и.{3}м\" but case insensitive."
|
||||
- text: "/z"
|
||||
arg_str: " \"(*LF).+\" r ascii"
|
||||
comment: "Search any ascii string with line feed is a newline."
|
||||
subcommands:
|
||||
- name: "/z"
|
||||
summary: String search.
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ typedef struct {
|
|||
RzRegex32 *re32;
|
||||
};
|
||||
void *jit_stack; ///< The JIT stack for this pattern. Must be used only by one thread at a time.
|
||||
RzRegexCompContext *ccontext;
|
||||
} RzRegexMulti;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -106,7 +107,7 @@ RZ_API RZ_OWN RzRegex16 *rz_regex_new_16(RZ_NONNULL const char *pattern, RzRegex
|
|||
RZ_API RZ_OWN RzRegex32 *rz_regex_new_32(RZ_NONNULL const char *pattern, RzRegexFlags cflags, RzRegexFlags jflags,
|
||||
RzRegexCompContext *ccontext);
|
||||
RZ_API RZ_OWN RzRegexMulti *rz_regex_new_multi(RZ_NONNULL const char *pattern, RzRegexFlags cflags, RzRegexFlags jflags,
|
||||
RzRegexCompContext *ccontext, RzRegexType type);
|
||||
RzRegexType type);
|
||||
RZ_API RZ_OWN RzRegex *rz_regex_new_bytes(RZ_NONNULL const ut8 *pattern, size_t pattern_len, RzRegexFlags cflags, RzRegexFlags jflags,
|
||||
RzRegexCompContext *ccontext);
|
||||
RZ_API void rz_regex_free(RZ_OWN RzRegex *regex);
|
||||
|
|
|
|||
|
|
@ -422,19 +422,19 @@ static RzDetectedString *setup_str_regex(const char *re_pattern, RzRegexFlags cf
|
|||
return NULL;
|
||||
case RZ_STRING_ENC_UTF8:
|
||||
case RZ_STRING_ENC_8BIT:
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, NULL, RZ_REGEX_UTF8);
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, RZ_REGEX_UTF8);
|
||||
break;
|
||||
case RZ_STRING_ENC_UTF16LE:
|
||||
case RZ_STRING_ENC_UTF16BE:
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, NULL, RZ_REGEX_UTF16);
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, RZ_REGEX_UTF16);
|
||||
break;
|
||||
case RZ_STRING_ENC_UTF32LE:
|
||||
case RZ_STRING_ENC_UTF32BE:
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, NULL, RZ_REGEX_UTF32);
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, RZ_REGEX_UTF32);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, NULL, RZ_REGEX_UTF8);
|
||||
re = rz_regex_new_multi(re_pattern, cflags, RZ_REGEX_DEFAULT, RZ_REGEX_UTF8);
|
||||
}
|
||||
if (!re) {
|
||||
RZ_LOG_ERROR("Failed to compile regex pattern: '%s'\n", re_pattern);
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ RZ_API RZ_OWN RzRegex32 *rz_regex_new_32(RZ_NONNULL const char *pattern, RzRegex
|
|||
* \brief Compile an Regex pattern of \p type.
|
||||
*
|
||||
* NOTE: The pattern and matching will always be in the host's endianness.
|
||||
* NOTE: The patterns are compiled with PCRE2_NEWLINE_NUL.
|
||||
*
|
||||
* \param pattern The regex pattern string. It must be an UTF-8 encoded string.
|
||||
* \param cflags The compilation flags or zero for default.
|
||||
|
|
@ -234,13 +235,11 @@ RZ_API RZ_OWN RzRegex32 *rz_regex_new_32(RZ_NONNULL const char *pattern, RzRegex
|
|||
* \param jflags The compilation flags for the JIT compiler.
|
||||
* You can pass RZ_REGEX_JIT_PARTIAL_SOFT or RZ_REGEX_JIT_PARTIAL_HARD if you
|
||||
* intend to use the pattern for partial matching. Otherwise set it to RZ_REGEX_DEFAULT.
|
||||
* \param ccontext A compile context or NULL.
|
||||
* \param type The string encoding type the pattern should match.
|
||||
*
|
||||
* \return The compiled regex or NULL in case of failure.
|
||||
*/
|
||||
RZ_API RZ_OWN RzRegexMulti *rz_regex_new_multi(RZ_NONNULL const char *pattern, RzRegexFlags cflags, RzRegexFlags jflags,
|
||||
RzRegexCompContext *ccontext, RzRegexType type) {
|
||||
RZ_API RZ_OWN RzRegexMulti *rz_regex_new_multi(RZ_NONNULL const char *pattern, RzRegexFlags cflags, RzRegexFlags jflags, RzRegexType type) {
|
||||
RzRegexMulti *re = RZ_NEW0(RzRegexMulti);
|
||||
if (!re) {
|
||||
return NULL;
|
||||
|
|
@ -255,16 +254,28 @@ RZ_API RZ_OWN RzRegexMulti *rz_regex_new_multi(RZ_NONNULL const char *pattern, R
|
|||
rz_warn_if_reached();
|
||||
free(re);
|
||||
return NULL;
|
||||
case RZ_REGEX_UTF8:
|
||||
case RZ_REGEX_UTF8: {
|
||||
RzRegexCompContext *ccontext = pcre2_compile_context_create_8(NULL);
|
||||
pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_NUL);
|
||||
re->re8 = rz_regex_new(pattern, cflags, jflags, ccontext);
|
||||
re->ccontext = ccontext;
|
||||
break;
|
||||
case RZ_REGEX_UTF16:
|
||||
}
|
||||
case RZ_REGEX_UTF16: {
|
||||
RzRegexCompContext *ccontext = pcre2_compile_context_create_16(NULL);
|
||||
pcre2_set_newline_16(ccontext, PCRE2_NEWLINE_NUL);
|
||||
re->re16 = rz_regex_new_16(pattern, cflags, jflags, ccontext);
|
||||
re->ccontext = ccontext;
|
||||
break;
|
||||
case RZ_REGEX_UTF32:
|
||||
}
|
||||
case RZ_REGEX_UTF32: {
|
||||
RzRegexCompContext *ccontext = pcre2_compile_context_create_32(NULL);
|
||||
pcre2_set_newline_32(ccontext, PCRE2_NEWLINE_NUL);
|
||||
re->re32 = rz_regex_new_32(pattern, cflags, jflags, ccontext);
|
||||
re->ccontext = ccontext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!re->re8 && !re->re16 && !re->re32) {
|
||||
free(re);
|
||||
return NULL;
|
||||
|
|
@ -457,12 +468,15 @@ RZ_API void rz_regex_free_multi(RZ_NULLABLE RZ_OWN RzRegexMulti *regex_multi) {
|
|||
switch (regex_multi->re_type) {
|
||||
case RZ_REGEX_UTF8:
|
||||
rz_regex_free(regex_multi->re8);
|
||||
pcre2_compile_context_free_8(regex_multi->ccontext);
|
||||
break;
|
||||
case RZ_REGEX_UTF16:
|
||||
rz_regex_free_16(regex_multi->re16);
|
||||
pcre2_compile_context_free_16(regex_multi->ccontext);
|
||||
break;
|
||||
case RZ_REGEX_UTF32:
|
||||
rz_regex_free_32(regex_multi->re32);
|
||||
pcre2_compile_context_free_32(regex_multi->ccontext);
|
||||
break;
|
||||
}
|
||||
#ifdef SUPPORTS_PCRE2_JIT
|
||||
|
|
|
|||
|
|
@ -299,11 +299,11 @@ e scr.columns=70
|
|||
/z??~:-6..
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
| /z (ABC*)D li # Search the exact string "(ABC*)D" but case
|
||||
insensitive.
|
||||
| /z \\d\\sC*\\w ri # Search the regular expression "\d\sC*\w" but
|
||||
case insensitive.
|
||||
| /z "и.{3}м" ei # Search the extended regular expression
|
||||
"и.{3}м" but case insensitive.
|
||||
| /z \\d\\sC*\\w ri # Search the regular expression "\d\sC*\w" but
|
||||
case insensitive.
|
||||
| /z "и.{3}м" ei # Search the extended regular expression
|
||||
"и.{3}м" but case insensitive.
|
||||
| /z "(*LF).+" r ascii # Search any ascii string with line feed is a
|
||||
newline.
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -1548,3 +1548,30 @@ EXPECT=<<EOF
|
|||
EOF
|
||||
EXPECT_ERR=
|
||||
RUN
|
||||
|
||||
NAME=Strings with new lines and \0 terminators
|
||||
FILE==
|
||||
CMDS=<<EOF
|
||||
# Searching in empty buffer should not find any strings
|
||||
/z .+ ri ascii
|
||||
|
||||
# Now write strings with new lines and NUL byte mixed
|
||||
wx 41414141414141004141414141410a0041414141414141004141414141410a00
|
||||
|
||||
# NUL is a new line by default
|
||||
/z .+ r ascii
|
||||
|
||||
# Overwrite default newline (NUL), \0 can be matched now with dot.
|
||||
/z "(*LF).+" r ascii
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00000000 7 hit.string.ascii.0 7
|
||||
0x00000008 7 hit.string.ascii.1 7
|
||||
0x00000010 7 hit.string.ascii.2 7
|
||||
0x00000018 7 hit.string.ascii.3 7
|
||||
0x00000000 14 hit.string.ascii.0 14
|
||||
0x0000000f 15 hit.string.ascii.1 15
|
||||
0x0000001f 481 hit.string.ascii.2 1e1
|
||||
EOF
|
||||
EXPECT_ERR=
|
||||
RUN
|
||||
|
|
|
|||
Loading…
Reference in a new issue