256 lines
5.1 KiB
C
256 lines
5.1 KiB
C
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_search.h>
|
|
|
|
static int ignoreMask(const ut8 *bm, int len) {
|
|
int i;
|
|
for (i = 0; i < len; i++) {
|
|
if (bm[i] != 0xff) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new(const ut8 *kwbuf, int kwlen, const ut8 *bmbuf, int bmlen, const char *data) {
|
|
RzSearchKeyword *kw;
|
|
if (kwlen < 1 || bmlen < 0) {
|
|
return NULL;
|
|
}
|
|
kw = RZ_NEW0(RzSearchKeyword);
|
|
if (!kw) {
|
|
return NULL;
|
|
}
|
|
kw->type = RZ_SEARCH_KEYWORD_TYPE_BINARY;
|
|
kw->data = (void *)data;
|
|
kw->keyword_length = kwlen;
|
|
kw->bin_keyword = malloc(kwlen);
|
|
if (!kw->bin_keyword) {
|
|
rz_search_keyword_free(kw);
|
|
return NULL;
|
|
}
|
|
memcpy(kw->bin_keyword, kwbuf, kwlen);
|
|
if (bmbuf && bmlen > 0 && !ignoreMask(bmbuf, bmlen)) {
|
|
kw->bin_binmask = malloc(bmlen);
|
|
if (!kw->bin_binmask) {
|
|
rz_search_keyword_free(kw);
|
|
return NULL;
|
|
}
|
|
memcpy(kw->bin_binmask, bmbuf, bmlen);
|
|
kw->binmask_length = bmlen;
|
|
} else {
|
|
kw->bin_binmask = NULL;
|
|
kw->binmask_length = 0;
|
|
}
|
|
return kw;
|
|
}
|
|
|
|
RZ_API void rz_search_keyword_free(RzSearchKeyword *kw) {
|
|
if (!kw) {
|
|
return;
|
|
}
|
|
free(kw->bin_binmask);
|
|
free(kw->bin_keyword);
|
|
free(kw);
|
|
}
|
|
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new_str(const char *kwbuf, const char *bmstr, const char *data, int ignore_case) {
|
|
RzSearchKeyword *kw;
|
|
ut8 *bmbuf = NULL;
|
|
int bmlen = 0;
|
|
|
|
if (bmstr) {
|
|
bmbuf = malloc(strlen(bmstr) + 1);
|
|
if (!bmbuf) {
|
|
return NULL;
|
|
}
|
|
bmlen = rz_hex_str2bin(bmstr, bmbuf);
|
|
if (bmlen < 1) {
|
|
RZ_FREE(bmbuf);
|
|
}
|
|
}
|
|
kw = rz_search_keyword_new((ut8 *)kwbuf, strlen(kwbuf), bmbuf, bmlen, data);
|
|
if (kw) {
|
|
kw->icase = ignore_case;
|
|
kw->type = RZ_SEARCH_KEYWORD_TYPE_STRING;
|
|
}
|
|
free(bmbuf);
|
|
return kw;
|
|
}
|
|
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new_wide(const char *kwbuf, const char *bmstr, const char *data, int ignore_case) {
|
|
RzSearchKeyword *kw;
|
|
int len;
|
|
const char *p2;
|
|
char *p, *str;
|
|
ut8 *bmbuf = NULL;
|
|
int bmlen = 0;
|
|
|
|
if (bmstr) {
|
|
bmbuf = malloc(strlen(bmstr) + 1);
|
|
if (!bmbuf) {
|
|
return NULL;
|
|
}
|
|
bmlen = rz_hex_str2bin(bmstr, bmbuf);
|
|
if (bmlen < 1) {
|
|
RZ_FREE(bmbuf);
|
|
}
|
|
}
|
|
|
|
len = strlen(kwbuf);
|
|
str = malloc((len + 1) * 2);
|
|
for (p2 = kwbuf, p = str; *p2;) {
|
|
RzRune ch;
|
|
int num_utf8_bytes = rz_utf8_decode((const ut8 *)p2, kwbuf + len - p2, &ch);
|
|
if (num_utf8_bytes < 1) {
|
|
eprintf("WARNING: Malformed UTF8 at pos %td\n", p2 - kwbuf);
|
|
p[0] = *p2;
|
|
p[1] = 0;
|
|
p2++;
|
|
p += 2;
|
|
continue;
|
|
}
|
|
if (ignore_case && ch <= 0xff) {
|
|
ch = tolower(ch);
|
|
}
|
|
int num_wide_bytes = rz_utf16le_encode((ut8 *)p, ch);
|
|
rz_warn_if_fail(num_wide_bytes != 0);
|
|
p2 += num_utf8_bytes;
|
|
p += num_wide_bytes;
|
|
}
|
|
|
|
kw = rz_search_keyword_new((ut8 *)str, p - str, bmbuf, bmlen, data);
|
|
free(str);
|
|
if (kw) {
|
|
kw->icase = ignore_case;
|
|
}
|
|
free(bmbuf);
|
|
return kw;
|
|
}
|
|
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new_hex(const char *kwstr, const char *bmstr, const char *data) {
|
|
RzSearchKeyword *kw;
|
|
ut8 *kwbuf, *bmbuf;
|
|
int kwlen, bmlen = 0;
|
|
|
|
if (!kwstr) {
|
|
return NULL;
|
|
}
|
|
|
|
kwbuf = malloc(strlen(kwstr) + 1);
|
|
if (!kwbuf) {
|
|
return NULL;
|
|
}
|
|
|
|
kwlen = rz_hex_str2bin(kwstr, kwbuf);
|
|
if (kwlen < 1) {
|
|
free(kwbuf);
|
|
return NULL;
|
|
}
|
|
|
|
bmbuf = NULL;
|
|
if (bmstr && *bmstr) {
|
|
bmbuf = malloc(strlen(bmstr) + 1);
|
|
if (!bmbuf) {
|
|
free(kwbuf);
|
|
return NULL;
|
|
}
|
|
bmlen = rz_hex_str2bin(bmstr, bmbuf);
|
|
if (bmlen < 1) {
|
|
free(bmbuf);
|
|
free(kwbuf);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
kw = rz_search_keyword_new(kwbuf, kwlen, bmbuf, bmlen, data);
|
|
free(kwbuf);
|
|
free(bmbuf);
|
|
return kw;
|
|
}
|
|
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new_hexmask(const char *kwstr, const char *data) {
|
|
RzSearchKeyword *ks = NULL;
|
|
ut8 *kw, *bm;
|
|
if (kwstr != NULL) {
|
|
int len = strlen(kwstr);
|
|
kw = malloc(len + 4);
|
|
bm = malloc(len + 4);
|
|
if (kw != NULL && bm != NULL) {
|
|
len = rz_hex_str2binmask(kwstr, (ut8 *)kw, (ut8 *)bm);
|
|
if (len < 0) {
|
|
len = -len - 1;
|
|
}
|
|
if (len > 0) {
|
|
ks = rz_search_keyword_new(kw, len, bm, len, data);
|
|
}
|
|
}
|
|
free(kw);
|
|
free(bm);
|
|
}
|
|
return ks;
|
|
}
|
|
|
|
/* Validate a regexp in the canonical format /<regexp>/<options> */
|
|
RZ_API RzSearchKeyword *rz_search_keyword_new_regexp(const char *str, const char *data) {
|
|
RzSearchKeyword *kw;
|
|
int i = 0, start, length;
|
|
|
|
while (isspace((const unsigned char)str[i])) {
|
|
i++;
|
|
}
|
|
|
|
if (str[i++] != '/') {
|
|
return NULL;
|
|
}
|
|
|
|
/* Find the fist non backslash-escaped slash */
|
|
int specials = 0;
|
|
for (start = i; str[i]; i++) {
|
|
if (str[i] == '/' && str[i - 1] != '\\') {
|
|
break;
|
|
} else if (str[i - 1] == '\\' && isalpha(str[i])) {
|
|
specials++;
|
|
}
|
|
}
|
|
|
|
if (str[i++] != '/') {
|
|
return NULL;
|
|
}
|
|
|
|
length = i - start - 1;
|
|
if ((length > 128) || (length < 1)) {
|
|
return NULL;
|
|
}
|
|
|
|
kw = RZ_NEW0(RzSearchKeyword);
|
|
if (!kw) {
|
|
return NULL;
|
|
}
|
|
|
|
kw->bin_keyword = malloc(length + 1);
|
|
if (!kw->bin_keyword) {
|
|
rz_search_keyword_free(kw);
|
|
return NULL;
|
|
}
|
|
|
|
kw->bin_keyword[length] = 0;
|
|
memcpy(kw->bin_keyword, str + start, length);
|
|
kw->keyword_length = length - specials;
|
|
kw->type = RZ_SEARCH_KEYWORD_TYPE_STRING;
|
|
kw->data = (void *)data;
|
|
|
|
/* Parse the options */
|
|
for (; str[i]; i++) {
|
|
switch (str[i]) {
|
|
case 'i':
|
|
kw->icase = true;
|
|
break;
|
|
default:
|
|
rz_search_keyword_free(kw);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return kw;
|
|
}
|