mirror of
https://github.com/radareorg/radare2
synced 2026-08-22 20:23:32 -04:00
228 lines
7.8 KiB
C
228 lines
7.8 KiB
C
#include <r_magic.h>
|
|
#include <r_util.h>
|
|
#include "minunit.h"
|
|
|
|
static bool check_magic_output(const char *magic_source, const ut8 *probe, size_t probe_len, const char *expected) {
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)magic_source, strlen (magic_source)), "text buffer load failed");
|
|
type = r_magic_buffer (ms, probe, probe_len);
|
|
mu_assert_notnull (type, "magic probe failed");
|
|
mu_assert_streq (type, expected, "magic match");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_load_text_buffer(void) {
|
|
const char magic_source[] =
|
|
"0\tstring\tABCD\ttext magic\n"
|
|
"!:mime\ttext/x-r2-magic\n";
|
|
const ut8 probe[] = "ABCD";
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)magic_source, sizeof (magic_source) - 1), "text buffer load failed");
|
|
r_magic_setflags (ms, R_MAGIC_MIME_TYPE);
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_notnull (type, "text magic probe failed");
|
|
mu_assert_streq (type, "text/x-r2-magic", "text magic match");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_load_compiled_buffer(void) {
|
|
struct {
|
|
struct r_magic header;
|
|
struct r_magic entry;
|
|
} db;
|
|
const ut8 probe[] = "ABCD";
|
|
const ut32 hdr[] = { MAGICNO, VERSIONNO };
|
|
RMagic *ms;
|
|
const char *type;
|
|
|
|
memset (&db, 0, sizeof (db));
|
|
memcpy (&db.header, hdr, sizeof (hdr));
|
|
db.entry.flag = BINTEST;
|
|
db.entry.reln = '=';
|
|
db.entry.vallen = 4;
|
|
db.entry.type = FILE_STRING;
|
|
db.entry.lineno = 1;
|
|
memcpy (db.entry.value.s, probe, sizeof (probe) - 1);
|
|
memcpy (db.entry.desc, "compiled magic", sizeof ("compiled magic"));
|
|
|
|
ms = r_magic_new (0);
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)&db, sizeof (db)), "compiled buffer load failed");
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_notnull (type, "compiled magic probe failed");
|
|
mu_assert_streq (type, "compiled magic", "compiled magic match");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_load_buffer_accepts_printf_suffixes(void) {
|
|
const char magic_source[] =
|
|
"0\tbyte\t0x41\tversion %c,\n"
|
|
"0\tbyte\t0x42\tvalue %d,\n"
|
|
"0\tstring\tABCD\tfrom '%s'\n"
|
|
"0\tstring\tWXYZ\t%.3s\n";
|
|
RMagic *ms = r_magic_new (0);
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)magic_source, sizeof (magic_source) - 1), "printf descriptions should load");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_buffer_formats_byte_char_descriptions(void) {
|
|
const char magic_source[] = "0\tbyte\t0x41\tversion %c,\n";
|
|
const ut8 probe[] = "ABCD";
|
|
|
|
return check_magic_output (magic_source, probe, sizeof (probe) - 1, "version A,");
|
|
}
|
|
|
|
static bool test_r_magic_buffer_formats_string_precision_descriptions(void) {
|
|
const char magic_source[] = "0\tstring\tABCD\t%.3s\n";
|
|
const ut8 probe[] = "ABCD";
|
|
|
|
return check_magic_output (magic_source, probe, sizeof (probe) - 1, "ABC");
|
|
}
|
|
|
|
static bool test_r_magic_load_buffer_accepts_long_regex(void) {
|
|
const char magic_source[] =
|
|
"0\tregex\t=^[\\ \\t]{0,10}(call|CALL)[\\ \\t]{1,10}(rxfunc|RXFUNC)\tOS/2 REXX batch file text\n";
|
|
const ut8 probe[] = "call rxfunc";
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)magic_source, sizeof (magic_source) - 1), "text buffer load failed");
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_null (type, "text magic should be disabled by default");
|
|
r_magic_setflags (ms, R_MAGIC_CHECK_TEXT);
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_notnull (type, "text magic probe failed");
|
|
mu_assert_streq (type, "OS/2 REXX batch file text", "text magic match");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_file_uses_slurp_and_buffer(void) {
|
|
const char magic_source[] = "0\tstring\tABCD\tfile magic\n";
|
|
char *filename = NULL;
|
|
const ut8 probe[] = "ABCD";
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
int fd;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffer (ms, (const ut8 *)magic_source, sizeof (magic_source) - 1), "text buffer load failed");
|
|
fd = r_file_mkstemp ("", &filename);
|
|
mu_assert_neq ((ut64)fd, (ut64)-1, "mkstemp failed");
|
|
mu_assert_eq ((int)write (fd, probe, sizeof (probe) - 1), (int)(sizeof (probe) - 1), "probe write failed");
|
|
close (fd);
|
|
type = r_magic_file (ms, filename);
|
|
mu_assert_notnull (type, "magic file probe failed");
|
|
mu_assert_streq (type, "file magic", "magic file match");
|
|
|
|
r_file_rm (filename);
|
|
free (filename);
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_load_buffers_merges_multiple_databases(void) {
|
|
const char magic_a[] = "0\tstring\tABCD\tmagic A\n";
|
|
const char magic_b[] = "0\tstring\tWXYZ\tmagic B\n";
|
|
const void *buffers[] = { magic_a, magic_b };
|
|
const size_t sizes[] = { sizeof (magic_a) - 1, sizeof (magic_b) - 1 };
|
|
const ut8 probe[] = "WXYZ";
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
mu_assert_true (r_magic_load_buffers (ms, buffers, sizes, 2), "buffer list load failed");
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_notnull (type, "merged magic probe failed");
|
|
mu_assert_streq (type, "magic B", "merged magic match");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_getflags_returns_current_flags(void) {
|
|
RMagic *ms = r_magic_new (0);
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
r_magic_setflags (ms, R_MAGIC_MIME_TYPE | R_MAGIC_RAW | R_MAGIC_CHECK_TEXT);
|
|
mu_assert_eq (r_magic_getflags (ms), R_MAGIC_MIME_TYPE | R_MAGIC_RAW | R_MAGIC_CHECK_TEXT, "flag roundtrip");
|
|
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_load_accepts_null_magic_path(void) {
|
|
const char magic_source[] = "0\tstring\tABCD\tenv magic\n";
|
|
const ut8 probe[] = "ABCD";
|
|
char *filename = NULL;
|
|
char *old_magic = r_sys_getenv ("MAGIC");
|
|
RMagic *ms = r_magic_new (0);
|
|
const char *type;
|
|
int fd;
|
|
|
|
mu_assert_notnull (ms, "r_magic_new () failed");
|
|
fd = r_file_mkstemp ("", &filename);
|
|
mu_assert_neq ((ut64)fd, (ut64)-1, "mkstemp failed");
|
|
mu_assert_eq ((int)write (fd, magic_source, sizeof (magic_source) - 1), (int)(sizeof (magic_source) - 1), "magic write failed");
|
|
close (fd);
|
|
mu_assert_eq (r_sys_setenv ("MAGIC", filename), 0, "setenv failed");
|
|
mu_assert_true (r_magic_load (ms, NULL), "null path load failed");
|
|
type = r_magic_buffer (ms, probe, sizeof (probe) - 1);
|
|
mu_assert_notnull (type, "env-backed magic probe failed");
|
|
mu_assert_streq (type, "env magic", "env-backed magic match");
|
|
|
|
if (old_magic) {
|
|
r_sys_setenv ("MAGIC", old_magic);
|
|
} else {
|
|
r_sys_setenv ("MAGIC", "");
|
|
}
|
|
free (old_magic);
|
|
r_file_rm (filename);
|
|
free (filename);
|
|
r_magic_free (ms);
|
|
mu_end;
|
|
}
|
|
|
|
static bool test_r_magic_api_version_matches_header_constant(void) {
|
|
mu_assert_eq (r_magic_api_version (), R_MAGIC_VERSION, "version mismatch");
|
|
mu_end;
|
|
}
|
|
|
|
int all_tests(void) {
|
|
mu_run_test (test_r_magic_load_text_buffer);
|
|
mu_run_test (test_r_magic_load_compiled_buffer);
|
|
mu_run_test (test_r_magic_load_buffer_accepts_printf_suffixes);
|
|
mu_run_test (test_r_magic_buffer_formats_byte_char_descriptions);
|
|
mu_run_test (test_r_magic_buffer_formats_string_precision_descriptions);
|
|
mu_run_test (test_r_magic_load_buffer_accepts_long_regex);
|
|
mu_run_test (test_r_magic_file_uses_slurp_and_buffer);
|
|
mu_run_test (test_r_magic_load_buffers_merges_multiple_databases);
|
|
mu_run_test (test_r_magic_getflags_returns_current_flags);
|
|
mu_run_test (test_r_magic_load_accepts_null_magic_path);
|
|
mu_run_test (test_r_magic_api_version_matches_header_constant);
|
|
return tests_passed != tests_run;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
(void)argc;
|
|
(void)argv;
|
|
return all_tests ();
|
|
}
|