From c2246ff478bb289674494f1ea47e15dff021e2fb Mon Sep 17 00:00:00 2001
From: Mooffie <mooffie@gmail.com>
Date: Sun, 25 Sep 2016 14:09:43 +0300
Subject: [PATCH 2/8] Hex patterns: report errors to the user.
Instead of silently accepting invalid patterns, we notify the user of errors.
---
lib/search/hex.c | 55 +++++++++++++++++++++++++++----
tests/lib/search/hex_translate_to_regex.c | 42 ++++++++++++++++++-----
2 files changed, 82 insertions(+), 15 deletions(-)
diff --git a/lib/search/hex.c b/lib/search/hex.c
index 3503ff8..a56d173 100644
a
|
b
|
|
39 | 39 | |
40 | 40 | /*** file scope macro definitions ****************************************************************/ |
41 | 41 | |
| 42 | typedef enum |
| 43 | { |
| 44 | MC_SEARCH_HEX_E_OK, |
| 45 | MC_SEARCH_HEX_E_NUM_OUT_OF_RANGE |
| 46 | } mc_search_hex_parse_error_t; |
| 47 | |
42 | 48 | /*** file scope type declarations ****************************************************************/ |
43 | 49 | |
44 | 50 | /*** file scope variables ************************************************************************/ |
… |
… |
|
46 | 52 | /*** file scope functions ************************************************************************/ |
47 | 53 | |
48 | 54 | static GString * |
49 | | mc_search__hex_translate_to_regex (const GString * astr) |
| 55 | mc_search__hex_translate_to_regex (const GString * astr, mc_search_hex_parse_error_t * error_ptr, |
| 56 | int *error_pos_ptr) |
50 | 57 | { |
51 | 58 | GString *buff; |
52 | 59 | gchar *tmp_str, *tmp_str2; |
53 | 60 | gsize tmp_str_len; |
54 | 61 | gsize loop = 0; |
| 62 | mc_search_hex_parse_error_t error = MC_SEARCH_HEX_E_OK; |
55 | 63 | |
56 | 64 | buff = g_string_sized_new (64); |
57 | 65 | tmp_str = g_strndup (astr->str, astr->len); |
… |
… |
mc_search__hex_translate_to_regex (const GString * astr) |
71 | 79 | g_strchug (tmp_str); /* trim leadind whitespaces */ |
72 | 80 | tmp_str_len = strlen (tmp_str); |
73 | 81 | |
74 | | while (loop < tmp_str_len) |
| 82 | while (loop < tmp_str_len && error == MC_SEARCH_HEX_E_OK) |
75 | 83 | { |
76 | 84 | unsigned int val; |
77 | 85 | int ptr; |
… |
… |
mc_search__hex_translate_to_regex (const GString * astr) |
80 | 88 | if (sscanf (tmp_str + loop, "%x%n", &val, &ptr)) |
81 | 89 | { |
82 | 90 | if (val > 255) |
83 | | loop++; |
| 91 | error = MC_SEARCH_HEX_E_NUM_OUT_OF_RANGE; |
84 | 92 | else |
85 | 93 | { |
86 | 94 | g_string_append_printf (buff, "\\x%02X", val); |
… |
… |
mc_search__hex_translate_to_regex (const GString * astr) |
109 | 117 | |
110 | 118 | g_free (tmp_str); |
111 | 119 | |
| 120 | if (error != MC_SEARCH_HEX_E_OK) |
| 121 | { |
| 122 | g_string_free (buff, TRUE); |
| 123 | if (error_ptr != NULL) |
| 124 | *error_ptr = error; |
| 125 | if (error_pos_ptr != NULL) |
| 126 | *error_pos_ptr = loop; |
| 127 | return NULL; |
| 128 | } |
| 129 | |
112 | 130 | return buff; |
113 | 131 | } |
114 | 132 | |
… |
… |
mc_search__cond_struct_new_init_hex (const char *charset, mc_search_t * lc_mc_se |
119 | 137 | mc_search_cond_t * mc_search_cond) |
120 | 138 | { |
121 | 139 | GString *tmp; |
| 140 | mc_search_hex_parse_error_t error; |
| 141 | int error_pos; |
122 | 142 | |
123 | 143 | g_string_ascii_down (mc_search_cond->str); |
124 | | tmp = mc_search__hex_translate_to_regex (mc_search_cond->str); |
125 | | g_string_free (mc_search_cond->str, TRUE); |
126 | | mc_search_cond->str = tmp; |
| 144 | tmp = mc_search__hex_translate_to_regex (mc_search_cond->str, &error, &error_pos); |
| 145 | if (tmp != NULL) |
| 146 | { |
| 147 | g_string_free (mc_search_cond->str, TRUE); |
| 148 | mc_search_cond->str = tmp; |
| 149 | mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond); |
| 150 | } |
| 151 | else |
| 152 | { |
| 153 | const char *desc; |
| 154 | |
| 155 | switch (error) |
| 156 | { |
| 157 | case MC_SEARCH_HEX_E_NUM_OUT_OF_RANGE: |
| 158 | desc = |
| 159 | _ |
| 160 | ("Number out of range (should be in byte range, 0 <= n <= 0xFF, expressed in hex)"); |
| 161 | break; |
| 162 | default: |
| 163 | desc = ""; |
| 164 | } |
127 | 165 | |
128 | | mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond); |
| 166 | lc_mc_search->error = MC_SEARCH_E_INPUT; |
| 167 | lc_mc_search->error_str = |
| 168 | g_strdup_printf (_("Hex pattern error at position %d:\n%s."), error_pos + 1, desc); |
| 169 | } |
129 | 170 | } |
130 | 171 | |
131 | 172 | /* --------------------------------------------------------------------------------------------- */ |
diff --git a/tests/lib/search/hex_translate_to_regex.c b/tests/lib/search/hex_translate_to_regex.c
index 34c131c..cd53486 100644
a
|
b
|
static const struct test_hex_translate_to_regex_ds |
34 | 34 | { |
35 | 35 | const char *input_value; |
36 | 36 | const char *expected_result; |
| 37 | mc_search_hex_parse_error_t expected_error; |
37 | 38 | } test_hex_translate_to_regex_ds[] = |
38 | 39 | { |
39 | 40 | { |
40 | 41 | /* Simplest case */ |
41 | 42 | "12 34", |
42 | | "\\x12\\x34" |
| 43 | "\\x12\\x34", |
| 44 | MC_SEARCH_HEX_E_OK |
43 | 45 | }, |
44 | 46 | { |
45 | 47 | /* Prefixes (0x, 0X) */ |
46 | 48 | "0x12 0X34", |
47 | | "\\x12\\x34" |
| 49 | "\\x12\\x34", |
| 50 | MC_SEARCH_HEX_E_OK |
48 | 51 | }, |
49 | 52 | { |
50 | 53 | /* Prefix "0" doesn't signify octal! Numbers are always interpreted in hex. */ |
51 | 54 | "012", |
52 | | "\\x12" |
| 55 | "\\x12", |
| 56 | MC_SEARCH_HEX_E_OK |
53 | 57 | }, |
54 | 58 | { |
55 | 59 | /* Extra whitespace (but not trailing one) */ |
56 | 60 | " 12 34", |
57 | | "\\x12\\x34" |
| 61 | "\\x12\\x34", |
| 62 | MC_SEARCH_HEX_E_OK |
58 | 63 | }, |
59 | 64 | { |
60 | 65 | /* Min/max values */ |
61 | 66 | "0 ff", |
62 | | "\\x00\\xFF" |
| 67 | "\\x00\\xFF", |
| 68 | MC_SEARCH_HEX_E_OK |
| 69 | }, |
| 70 | { |
| 71 | /* Error: Number out of range */ |
| 72 | "100", |
| 73 | NULL, |
| 74 | MC_SEARCH_HEX_E_NUM_OUT_OF_RANGE |
| 75 | }, |
| 76 | { |
| 77 | /* Error: Number out of range (negative) */ |
| 78 | "-1", |
| 79 | NULL, |
| 80 | MC_SEARCH_HEX_E_NUM_OUT_OF_RANGE |
63 | 81 | }, |
64 | 82 | }; |
65 | 83 | /* *INDENT-ON* */ |
… |
… |
START_PARAMETRIZED_TEST (test_hex_translate_to_regex, test_hex_translate_to_rege |
72 | 90 | /* given */ |
73 | 91 | GString *tmp = g_string_new (data->input_value); |
74 | 92 | GString *dest_str; |
| 93 | mc_search_hex_parse_error_t error; |
75 | 94 | |
76 | 95 | /* when */ |
77 | | dest_str = mc_search__hex_translate_to_regex (tmp); |
| 96 | dest_str = mc_search__hex_translate_to_regex (tmp, &error, NULL); |
78 | 97 | |
79 | 98 | /* then */ |
80 | 99 | g_string_free (tmp, TRUE); |
81 | 100 | |
82 | | mctest_assert_str_eq (dest_str->str, data->expected_result); |
83 | | g_string_free (dest_str, TRUE); |
| 101 | if (dest_str != NULL) |
| 102 | { |
| 103 | mctest_assert_str_eq (dest_str->str, data->expected_result); |
| 104 | g_string_free (dest_str, TRUE); |
| 105 | } |
| 106 | else |
| 107 | { |
| 108 | mctest_assert_int_eq (error, data->expected_error); |
| 109 | } |
84 | 110 | } |
85 | 111 | /* *INDENT-OFF* */ |
86 | 112 | END_PARAMETRIZED_TEST |