Better false-positives detection in rz_scan_strings (#2691)

* Improved false-positive detection in str_search

This commit adds the following features:
- Extend the false-positive check on ASCII frequencies to all UTF strings
- Add a global option to activate/deactivate di check
- Improve the false-positive heuristic by adding a special case for extended-ASCII strings
This commit is contained in:
Luca Borzacchiello 2022-06-14 16:14:13 +02:00 committed by GitHub
parent 9c2c5fa495
commit 2d69ecbb22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 161 additions and 78 deletions

View file

@ -93,7 +93,8 @@ static void string_scan_range(RzList *list, RzBinFile *bf, size_t min, const ut6
.buf_size = 2048,
.max_uni_blocks = 4,
.min_str_length = min,
.prefer_big_endian = false
.prefer_big_endian = false,
.check_ascii_freq = bf->rbin->strseach_check_ascii_freq
};
int count = rz_scan_strings(bf->buf, str_list, &scan_opt, from, to, type);

View file

@ -1164,6 +1164,13 @@ static bool cb_str_escbslash(void *user, void *data) {
return true;
}
static bool cb_strsearch_check_ascii_freq(void *user, void *data) {
RzCore *core = (RzCore *)user;
RzConfigNode *node = (RzConfigNode *)data;
core->bin->strseach_check_ascii_freq = node->i_value;
return true;
}
static bool cb_completion_maxtab(void *user, void *data) {
RzCore *core = (RzCore *)user;
RzConfigNode *node = (RzConfigNode *)data;
@ -3588,6 +3595,8 @@ RZ_API int rz_core_config_init(RzCore *core) {
/* str */
SETCB("str.escbslash", "false", &cb_str_escbslash, "Escape the backslash");
SETCB("str.search.check_ascii_freq", "true", &cb_strsearch_check_ascii_freq,
"Perform ASCII frequency analysis when looking for false positives during string search");
/* search */
SETCB("search.contiguous", "true", &cb_contiguous, "Accept contiguous/adjacent search hits");

View file

@ -438,7 +438,8 @@ static bool meta_string_guess_add(RzCore *core, ut64 addr, size_t limit, char **
.buf_size = 2048,
.max_uni_blocks = 4,
.min_str_length = 4,
.prefer_big_endian = big_endian
.prefer_big_endian = big_endian,
.check_ascii_freq = bf->rbin->strseach_check_ascii_freq
};
RzList *str_list = rz_list_new();
if (!str_list) {

View file

@ -375,6 +375,7 @@ struct rz_bin_t {
bool verbose;
bool use_xtr; // use extract plugins when loading a file?
bool use_ldr; // use loader plugins when loading a file?
bool strseach_check_ascii_freq; // str.search.check_ascii_freq
RzStrConstPool constpool;
bool is_reloc_patched; // used to indicate whether relocations were patched or not
RzDemangler *demangler;

View file

@ -28,7 +28,8 @@ typedef struct {
size_t buf_size; ///< Maximum size of a detected string
size_t max_uni_blocks; ///< Maximum number of unicode blocks
size_t min_str_length; ///< Minimum string length
bool prefer_big_endian; //< True if the preferred endianess for UTF strings is big-endian
bool prefer_big_endian; ///< True if the preferred endianess for UTF strings is big-endian
bool check_ascii_freq; ///< If true, perform check on ASCII frequencies when looking for false positives
} RzUtilStrScanOptions;
RZ_API void rz_detected_string_free(RzDetectedString *str);

View file

@ -13,6 +13,12 @@ typedef enum {
STRING_OK,
} FalsePositiveResult;
typedef struct {
int num_ascii;
int num_ascii_extended;
int num_chars;
} UTF8StringInfo;
// clang-format off
static const ut8 LATIN1_CLASS[256] = {
0,0,0,0,0,0,0,0, 0,1,1,0,0,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
@ -75,9 +81,35 @@ static inline bool is_c_escape_sequence(char ch) {
return strchr("\b\v\f\n\r\t\a\033\\", ch);
}
static UTF8StringInfo calculate_utf8_string_info(ut8 *str, int size) {
UTF8StringInfo res = {
.num_ascii = 0,
.num_ascii_extended = 0,
.num_chars = 0
};
const ut8 *str_ptr = str;
const ut8 *str_end = str + size;
RzRune ch;
while (str_ptr < str_end) {
int ch_bytes = rz_utf8_decode(str_ptr, str_end - str_ptr, &ch);
if (!ch_bytes)
break;
res.num_chars += 1;
if (ch < 0x80u)
res.num_ascii += 1;
if (ch < 0x100u)
res.num_ascii_extended += 1;
str_ptr += ch_bytes;
}
return res;
}
static FalsePositiveResult reduce_false_positives(const RzUtilStrScanOptions *opt, ut8 *str, int size, RzStrEnc str_type) {
int i, num_blocks, *block_list;
int *freq_list = NULL, expected_ascii, actual_ascii, num_chars;
int i;
switch (str_type) {
case RZ_STRING_ENC_8BIT: {
@ -94,35 +126,32 @@ static FalsePositiveResult reduce_false_positives(const RzUtilStrScanOptions *op
case RZ_STRING_ENC_UTF8:
case RZ_STRING_ENC_UTF16LE:
case RZ_STRING_ENC_UTF32LE:
num_blocks = 0;
block_list = rz_utf_block_list((const ut8 *)str, size - 1,
str_type == RZ_STRING_ENC_UTF16LE ? &freq_list : NULL);
case RZ_STRING_ENC_UTF16BE:
case RZ_STRING_ENC_UTF32BE: {
int num_blocks = 0;
int *block_list = rz_utf_block_list((const ut8 *)str, size - 1, NULL);
if (block_list) {
for (i = 0; block_list[i] != -1; i++) {
num_blocks++;
}
}
if (freq_list) {
num_chars = 0;
actual_ascii = 0;
for (i = 0; freq_list[i] != -1; i++) {
num_chars += freq_list[i];
if (!block_list[i]) { // ASCII
actual_ascii = freq_list[i];
}
}
free(freq_list);
expected_ascii = num_blocks ? num_chars / num_blocks : 0;
if (actual_ascii > expected_ascii) {
free(block_list);
return RETRY_ASCII;
}
}
free(block_list);
UTF8StringInfo str_info = calculate_utf8_string_info(str, size);
if (str_info.num_ascii_extended == str_info.num_chars) {
return STRING_OK;
}
int expected_ascii = num_blocks ? str_info.num_chars / num_blocks : 0;
if (opt->check_ascii_freq && str_info.num_ascii > expected_ascii) {
return RETRY_ASCII;
}
if (num_blocks > opt->max_uni_blocks) {
return SKIP_STRING;
}
break;
}
default:
break;
}
@ -252,8 +281,9 @@ static RzDetectedString *process_one_string(const ut8 *buf, const ut64 from, ut6
}
}
int strbuf_size = i;
if (runes >= opt->min_str_length) {
FalsePositiveResult false_positive_result = reduce_false_positives(opt, strbuf, i - 1, str_type);
FalsePositiveResult false_positive_result = reduce_false_positives(opt, strbuf, strbuf_size, str_type);
if (false_positive_result == SKIP_STRING) {
return NULL;
} else if (false_positive_result == RETRY_ASCII) {
@ -273,7 +303,7 @@ static RzDetectedString *process_one_string(const ut8 *buf, const ut64 from, ut6
ds->addr -= off_adj;
ds->size += off_adj;
ds->string = rz_str_ndup((const char *)strbuf, i);
ds->string = rz_str_ndup((const char *)strbuf, strbuf_size);
return ds;
}

View file

@ -17,7 +17,7 @@ EXPECT=<<EOF
0x0063e49b str.version
0x0063e4ac str.HTTP_version
0x0063e566 str.
14145
12879
EOF
RUN
@ -44,7 +44,7 @@ EXPECT=<<EOF
;-- str.flag:
;-- str.sort:
;-- str.sync:
13207
12263
EOF
RUN
@ -67,7 +67,7 @@ EXPECT=<<EOF
0x0065de6d str.version
0x0065de8a str.HTTP_version
0x0065dfe6 str.
13360
13171
EOF
RUN
@ -129,7 +129,7 @@ EXPECT=<<EOF
0x0027401c str.btcctl.conf
0x00274090 str.rpc.cert
0x00274104 str.rpc.cert
13466
12807
EOF
RUN
@ -212,7 +212,7 @@ EXPECT=<<EOF
0x0026e4b8 str.btcctl.conf
0x0026e53c str.rpc.cert
0x0026e5c0 str.rpc.cert
15577
14650
EOF
RUN
@ -249,7 +249,7 @@ EOF
EXPECT=<<EOF
1788
0x004a699b str.hello__hacktivity
9074
8531
compiler go1.15
EOF
RUN

View file

@ -18,11 +18,11 @@ score candidate
4 0x08000000
EOF
EXPECT_ERR=<<EOF
INFO: basefind: located 7 strings
INFO: basefind: located 6 strings
INFO: basefind: located 1459 pointers
INFO: basefind: located 7 strings
INFO: basefind: located 6 strings
INFO: basefind: located 1459 pointers
INFO: basefind: located 7 strings
INFO: basefind: located 6 strings
INFO: basefind: located 1459 pointers
EOF
RUN

View file

@ -4351,19 +4351,21 @@ RUN
NAME=iz utf16le
FILE=bins/elf/strenc
ARGS=-e str.search.check_ascii_freq=false
CMDS=<<EOF
e str.escbslash=true
iz~green
iz~wall
EOF
EXPECT=<<EOF
5 0x00002248 0x00402248 48 97 .rodata utf16le \nutf16le> \\u00a2\\u20ac\\U00010348 in green:\e[32m
8 0x000022c8 0x004022c8 33 68 .rodata utf16le is a wall with no embedded zeros\n
5 0x00002248 0x00402248 57 118 .rodata utf16le \nutf16le> \\u00a2\\u20ac\\U00010348 in green:\e[32m ¢€𐍈 \e[0m\n blocks=Basic Latin,Latin-1 Supplement,Currency Symbols,Gothic
7 0x000022c8 0x004022c8 33 68 .rodata utf16le is a wall with no embedded zeros\n
EOF
RUN
NAME=iz/izz utf32le
FILE=bins/elf/strenc
ARGS=-e str.search.check_ascii_freq=false
CMDS=<<EOF
e str.escbslash=true
iz~cyan
@ -4371,9 +4373,9 @@ iz~Mountain
izz~Linux_wide
EOF
EXPECT=<<EOF
17 0x0000258c 0x0040258c 55 224 .rodata utf32le utf32le> \\u00a2\\u20ac\\U00010348 in cyan:\e[36m ¢€𐍈 \e[0m\n blocks=Basic Latin,Latin-1 Supplement,Currency Symbols,Gothic
18 0x0000266c 0x0040266c 48 196 .rodata utf32le Mountain range with embedded quad zeros: 𐌀A𐌀A𐌀A\n blocks=Basic Latin,Old Italic
136 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
16 0x0000258c 0x0040258c 55 224 .rodata utf32le utf32le> \\u00a2\\u20ac\\U00010348 in cyan:\e[36m ¢€𐍈 \e[0m\n blocks=Basic Latin,Latin-1 Supplement,Currency Symbols,Gothic
17 0x0000266c 0x0040266c 48 196 .rodata utf32le Mountain range with embedded quad zeros: 𐌀A𐌀A𐌀A\n blocks=Basic Latin,Old Italic
135 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
EOF
RUN
@ -4385,23 +4387,23 @@ iz~SRSPRHEX
iz~SRSTASK
EOF
EXPECT=<<EOF
14 0x000002f6 0x000002f6 8 9 ibm037 SRSGENER
19 0x000004dc 0x000004dc 8 9 ibm037 SRSGENER
22 0x00000668 0x00000668 92 93 ibm037 SRSGENER_03/06/08_14.16 SRS Version 1.3.0_BASE COPYRIGHT 1998-2008 DAVID W DANNER ALL RIG
66 0x00001682 0x00001682 30 31 ibm037 SRSGENERNO *SRS> NONHELD
132 0x00002faa 0x00002faa 49 50 ibm037 SHUTDOWNSRSOPTS SRSTBLK SRSGENERALL STARTINGS
10 0x0000029a 0x0000029a 8 9 ibm037 SRSPRHEX
17 0x00000362 0x00000362 8 9 ibm037 SRSPRHEX
67 0x000016d4 0x000016d4 8 9 ibm037 SRSPRHEX
70 0x00001861 0x00001861 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
74 0x0000191f 0x0000191f 9 10 ibm037 ÏSRSPRHEX
138 0x0000315b 0x0000315b 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
142 0x0000323f 0x0000323f 9 10 ibm037 3SRSPRHEX
217 0x00004c0f 0x00004c0f 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
18 0x000003ba 0x000003ba 8 9 ibm037 SRSTASK
98 0x00002540 0x00002540 17 18 ibm037 ­bå0­«SRSTASK  \-
141 0x00003230 0x00003230 8 9 ibm037 SRSTASK
147 0x000033e4 0x000033e4 103 104 ibm037 SRSTASK_12/31/08_20.31 SRS Version 1.3.0_A13001 COPYRIGHT 1998-2008 DAVID W DANNER ALL RIGHTS RESERVED
14 0x000002f6 0x000002f6 8 9 ibm037 SRSGENER
19 0x000004dc 0x000004dc 8 9 ibm037 SRSGENER
22 0x00000668 0x00000668 92 93 ibm037 SRSGENER_03/06/08_14.16 SRS Version 1.3.0_BASE COPYRIGHT 1998-2008 DAVID W DANNER ALL RIG
63 0x00001682 0x00001682 30 31 ibm037 SRSGENERNO *SRS> NONHELD
114 0x00002faa 0x00002faa 49 50 ibm037 SHUTDOWNSRSOPTS SRSTBLK SRSGENERALL STARTINGS
10 0x0000029a 0x0000029a 8 9 ibm037 SRSPRHEX
17 0x00000362 0x00000362 8 9 ibm037 SRSPRHEX
64 0x000016d4 0x000016d4 8 9 ibm037 SRSPRHEX
67 0x00001861 0x00001861 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
71 0x0000191f 0x0000191f 9 10 ibm037 ÏSRSPRHEX
120 0x0000315b 0x0000315b 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
124 0x0000323f 0x0000323f 9 10 ibm037 3SRSPRHEX
190 0x00004c0f 0x00004c0f 27 28 ibm037 SRSPRHEX_03/06/08_14.17°Ö}\f
18 0x000003ba 0x000003ba 8 9 ibm037 SRSTASK
90 0x00002540 0x00002540 17 18 ibm037 ­bå0­«SRSTASK  \-
123 0x00003230 0x00003230 8 9 ibm037 SRSTASK
129 0x000033e4 0x000033e4 103 104 ibm037 SRSTASK_12/31/08_20.31 SRS Version 1.3.0_A13001 COPYRIGHT 1998-2008 DAVID W DANNER ALL RIGHTS RESERVED
EOF
RUN
@ -4414,8 +4416,8 @@ e str.escbslash=false
iz~Linux_wide
EOF
EXPECT=<<EOF
16 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
16 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
17 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
17 0x00002528 0x00402528 24 100 .rodata utf32le \tLinux_wide\esc: \e[0m¡\r\n blocks=Basic Latin,Latin-1 Supplement
EOF
RUN
@ -4428,7 +4430,7 @@ iz~123456
EOF
EXPECT=<<EOF
1 0x0000060c 0x0040060c 6 28 .rodata utf32le ABCDEF
2 0x00000650 0x00400650 10 44 .rodata utf32le abcdef𐍈 g blocks=Basic Latin,Gothic
2 0x00000650 0x00400650 6 25 .rodata utf32le abcdef
3 0x00000694 0x00400694 6 28 .rodata utf32le 123456
EOF
RUN
@ -4574,12 +4576,13 @@ RUN
NAME=izj unicode blocks
FILE=bins/elf/strenc
ARGS=-e str.search.check_ascii_freq=false
CMDS=<<EOF
e bin.str.purge=all,!4202996,!4203007,!4203208
izj
EOF
EXPECT=<<EOF
[{"vaddr":4202996,"paddr":8692,"ordinal":2,"size":11,"length":10,"section":".rodata","type":"ascii","string":"en_US.utf8"},{"vaddr":4203007,"paddr":8703,"ordinal":3,"size":61,"length":54,"section":".rodata","type":"utf8","string":"utf8> \\\\u00a2\\\\u20ac\\\\U00010348 in yellow:\\e[33m ¢€𐍈 \\e[0m\\n","blocks":["Basic Latin","Latin-1 Supplement","Currency Symbols","Gothic"]},{"vaddr":4203208,"paddr":8904,"ordinal":8,"size":68,"length":33,"section":".rodata","type":"utf16le","string":"is a wall with no embedded zeros\\n"}]
[{"vaddr":4202996,"paddr":8692,"ordinal":2,"size":11,"length":10,"section":".rodata","type":"ascii","string":"en_US.utf8"},{"vaddr":4203007,"paddr":8703,"ordinal":3,"size":61,"length":54,"section":".rodata","type":"utf8","string":"utf8> \\\\u00a2\\\\u20ac\\\\U00010348 in yellow:\\e[33m ¢€𐍈 \\e[0m\\n","blocks":["Basic Latin","Latin-1 Supplement","Currency Symbols","Gothic"]},{"vaddr":4203208,"paddr":8904,"ordinal":7,"size":68,"length":33,"section":".rodata","type":"utf16le","string":"is a wall with no embedded zeros\\n"}]
EOF
RUN
@ -4590,7 +4593,7 @@ e bin.str.purge=all,!4195920
izzj
EOF
EXPECT=<<EOF
[{"vaddr":4195920,"paddr":1616,"ordinal":13,"size":44,"length":10,"section":".rodata","type":"utf32le","string":"abcdef𐍈 g","blocks":["Basic Latin","Gothic"]}]
[{"vaddr":4195920,"paddr":1616,"ordinal":13,"size":25,"length":6,"section":".rodata","type":"utf32le","string":"abcdef"}]
EOF
RUN
@ -4643,7 +4646,7 @@ e bin.str.purge=all,!0x413220-0x413235
EOF
EXPECT=<<EOF
--1--
1100 0x00012420 0x00412420 5 6 .text ascii AWAVA
1089 0x00012420 0x00412420 5 6 .text ascii AWAVA
--2--
--3--
0 0x000131d8 0x004131d8 11 12 .rodata ascii dev_ino_pop
@ -5218,7 +5221,7 @@ NAME=izz
FILE=bins/mach0/fatmach0-3true
CMDS=izz~http~codesigning
EXPECT=<<EOF
97 0x00003f3c 0x100002f3c 47 48 ascii ,http://www.apple.com/appleca/codesigning.crl0\r
93 0x00003f3c 0x100002f3c 47 48 ascii ,http://www.apple.com/appleca/codesigning.crl0\r
EOF
RUN

View file

@ -420,7 +420,6 @@ RUN
NAME=Csb, Cs. and Cs.l
FILE=bins/pe/testapp-msvc64.exe
BROKEN=1
CMDS=<<EOF
e str.escbslash=true
s 0x140016018
@ -452,11 +451,12 @@ ascii[2] "\t"
0x140016018 ascii[2] "\t"
;-- str.wide_esc:___0m:
0x140016018 .string "\t" ; len=2
Csw 19 @ 0x140016018 # \twide\\esc: \e[0m\xa1\r\n
"\twide\\esc: \e[0m\xa1\r\n"
ut16le[15] "\twide\\esc: \e[0m\xa1\r\n"
Csw 38 @ 0x140016018 # \twide\\esc: \e[0m\u00a1\r\n
"\twide\\esc: \e[0m\u00a1\r\n"
utf16le[38] "\twide\\esc: \e[0m\u00a1\r\n"
0x140016018 utf16le[38] "\twide\\esc: \e[0m\u00a1\r\n"
;-- str.wide_esc:___0m:
0x140016018 .string "\twide\\esc: \e[0m\xa1\r\n" ; len=19
0x140016018 .string "\twide\\esc: \e[0m\xc2\xa1\r\n" ; len=38
0x140016018 ascii[4] "\t"
0x140016018 ascii[4] "\t"
EOF
@ -479,15 +479,16 @@ Cs
Cslj
EOF
EXPECT=<<EOF
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBt","enc":"utf16le","ascii":true}]
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBtwqENCg==","enc":"utf16le","ascii":false}]
[{"offset":5368799256,"type":"Cs","name":"CQ==","enc":"8bit","ascii":true}]
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBt","enc":"utf16le","ascii":true}]
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBt","enc":"utf16le","ascii":true}]
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBtwqENCg==","enc":"utf16le","ascii":false}]
[{"offset":5368799256,"type":"Cs","name":"CXdpZGVcZXNjOiAbWzBtwqENCg==","enc":"utf16le","ascii":false}]
EOF
RUN
NAME=Cs8
FILE=bins/elf/strenc
ARGS=-e str.search.check_ascii_freq=false
CMDS=<<EOF
e str.escbslash=true
s 0x004021ff
@ -521,7 +522,7 @@ RUN
NAME=Cs8 and Cslj
FILE=bins/elf/strenc
ARGS=-e bin.str.purge=all,!0x004021ff
ARGS=-e bin.str.purge=all,!0x004021ff -e str.search.check_ascii_freq=false
CMDS=<<EOF
s 0x004021ff
Csl

View file

@ -2,7 +2,7 @@ NAME=ELF: arm64 relocs crashing
FILE==
CMDS=!!rz-bin -qzz bins/elf/librsjni_androix.so~?
EXPECT=<<EOF
566
561
EOF
RUN

View file

@ -173,7 +173,7 @@ NAME=rz-bin -zz pe
FILE=bins/pe/ioli/w32/crackme0x00.exe
CMDS=!rz-bin -zz ${RZ_FILE} | grep "Password:"
EXPECT=<<EOF
102 0x00002619 0x00404019 10 11 (.rdata) ascii Password:
086 0x00002619 0x00404019 10 11 (.rdata) ascii Password:
EOF
RUN

View file

@ -8,7 +8,8 @@ static RzUtilStrScanOptions g_opt = {
.buf_size = 2048,
.max_uni_blocks = 4,
.min_str_length = 4,
.prefer_big_endian = false
.prefer_big_endian = false,
.check_ascii_freq = true
};
bool test_rz_scan_strings_detect_ascii(void) {
@ -184,7 +185,7 @@ bool test_rz_scan_strings_detect_utf16_le_special_chars(void) {
mu_assert_eq(n, 1, "rz_scan_strings utf16le, number of strings");
RzDetectedString *s = rz_list_get_n(str_list, 0);
mu_assert_streq(s->string, "\twide\\esc: \x1b[0m", "rz_scan_strings utf16le, different string");
mu_assert_streq(s->string, "\twide\\esc: \x1b[0m\xc2\xa1\r\n", "rz_scan_strings utf16le, different string");
mu_assert_eq(s->addr, 0, "rz_scan_strings utf16le, address");
mu_assert_eq(s->type, RZ_STRING_ENC_UTF16LE, "rz_scan_strings utf16le, string type");
@ -308,6 +309,40 @@ bool test_rz_scan_strings_utf16_be(void) {
mu_end;
}
bool test_rz_scan_strings_extended_ascii(void) {
static const unsigned char str[] =
"Immensità s'annega il pensier mio: E il naufragar m'è dolce in questo mare.\x00"
"Ich sah, wie Doris bei Damöten stand, er nahm sie zärtlich bei der Hand.\00"
"Dans l'éblouissante clarté de leur premier amour.\x00";
RzBuffer *buf = rz_buf_new_with_bytes(str, sizeof(str));
RzList *str_list = rz_list_new();
int n = rz_scan_strings(buf, str_list, &g_opt, 0, buf->methods->get_size(buf) - 1, RZ_STRING_ENC_UTF8);
mu_assert_eq(n, 3, "rz_scan_strings extended_ascii, number of strings");
RzDetectedString *s_it = rz_list_get_n(str_list, 0);
RzDetectedString *s_de = rz_list_get_n(str_list, 1);
RzDetectedString *s_fr = rz_list_get_n(str_list, 2);
mu_assert_streq(s_it->string, "Immensità s'annega il pensier mio: E il naufragar m'è dolce in questo mare.",
"rz_scan_strings extended_ascii, different strings IT");
mu_assert_streq(s_de->string, "Ich sah, wie Doris bei Damöten stand, er nahm sie zärtlich bei der Hand.",
"rz_scan_strings extended_ascii, different strings DE");
mu_assert_streq(s_fr->string, "Dans l'éblouissante clarté de leur premier amour.",
"rz_scan_strings extended_ascii, different strings FR");
rz_detected_string_free(s_it);
rz_detected_string_free(s_de);
rz_detected_string_free(s_fr);
rz_list_free(str_list);
rz_buf_free(buf);
mu_end;
}
bool all_tests() {
mu_run_test(test_rz_scan_strings_detect_ascii);
mu_run_test(test_rz_scan_strings_detect_ibm037);
@ -317,8 +352,9 @@ bool all_tests() {
mu_run_test(test_rz_scan_strings_detect_utf16_be);
mu_run_test(test_rz_scan_strings_detect_utf32_le);
mu_run_test(test_rz_scan_strings_detect_utf32_be);
mu_run_test(test_rz_scan_strings_utf16_be);
mu_run_test(test_rz_scan_strings_extended_ascii);
return tests_passed != tests_run;
}