dfilter: Fix invalid character constant error message
This reverts commit d635ff4933
.
A charconst cannot be a value string, for that reason it is not
redundant with unparsed.
Maybe character constants should be parsed in the lexical scanner
instead.
Before:
Filter: ip.proto == '\g'
dftest: "'\g'" cannot be found among the possible values for ip.proto.
After:
Filter: ip.proto == '\g'
dftest: "'\g'" isn't a valid character constant.
This commit is contained in:
parent
b657396d44
commit
7028646f9e
|
@ -148,8 +148,7 @@ entity(E) ::= STRING(S).
|
|||
}
|
||||
entity(E) ::= CHARCONST(C).
|
||||
{
|
||||
/* A charconst uses "unparsed" semantic rules. */
|
||||
E = stnode_new_unparsed(df_lval_value(C));
|
||||
E = stnode_new_charconst(df_lval_value(C));
|
||||
df_lval_free(C);
|
||||
}
|
||||
entity(E) ::= UNPARSED(U).
|
||||
|
|
|
@ -433,6 +433,7 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
/* This is OK */
|
||||
break;
|
||||
case STTYPE_STRING:
|
||||
case STTYPE_CHARCONST:
|
||||
case STTYPE_UNPARSED:
|
||||
FAIL(dfw, "\"%s\" is neither a field nor a protocol name.",
|
||||
stnode_todisplay(st_arg1));
|
||||
|
@ -539,6 +540,31 @@ check_function(dfwork_t *dfw, stnode_t *st_node)
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert a character constant to a 1-byte BYTE_STRING containing the
|
||||
* character. */
|
||||
WS_RETNONNULL
|
||||
static fvalue_t *
|
||||
dfilter_fvalue_from_charconst_string(dfwork_t *dfw, ftenum_t ftype, stnode_t *st, gboolean allow_partial_value)
|
||||
{
|
||||
fvalue_t *fvalue;
|
||||
const char *s = stnode_data(st);
|
||||
|
||||
fvalue = fvalue_from_unparsed(FT_CHAR, s, allow_partial_value,
|
||||
dfw->error_message == NULL ? &dfw->error_message : NULL);
|
||||
if (fvalue == NULL)
|
||||
THROW(TypeError);
|
||||
|
||||
char *temp_string;
|
||||
/* It's valid. Create a 1-byte BYTE_STRING from its value. */
|
||||
temp_string = g_strdup_printf("%02x", fvalue->value.uinteger);
|
||||
fvalue_free(fvalue);
|
||||
fvalue = fvalue_from_unparsed(ftype, temp_string, allow_partial_value, NULL);
|
||||
ws_assert(fvalue);
|
||||
g_free(temp_string);
|
||||
|
||||
return fvalue;
|
||||
}
|
||||
|
||||
/* If the LHS of a relation test is a FIELD, run some checks
|
||||
* and possibly some modifications of syntax tree nodes. */
|
||||
static void
|
||||
|
@ -578,7 +604,8 @@ check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
|
|||
hfinfo2->abbrev, ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
|
||||
type2 == STTYPE_CHARCONST) {
|
||||
/* Skip incompatible fields */
|
||||
while (hfinfo1->same_name_prev_id != -1 &&
|
||||
((type2 == STTYPE_STRING && ftype1 != FT_STRING && ftype1!= FT_STRINGZ) ||
|
||||
|
@ -590,6 +617,17 @@ check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
|
|||
if (type2 == STTYPE_STRING) {
|
||||
fvalue = dfilter_fvalue_from_string(dfw, ftype1, st_arg2, hfinfo1);
|
||||
}
|
||||
else if (type2 == STTYPE_CHARCONST && st_op == TEST_OP_CONTAINS) {
|
||||
/* The RHS should be the same type as the LHS,
|
||||
* but a character is just a one-byte byte
|
||||
* string. */
|
||||
fvalue = dfilter_fvalue_from_charconst_string(dfw, ftype1, st_arg2, allow_partial_value);
|
||||
}
|
||||
else if (type2 == STTYPE_CHARCONST) {
|
||||
/* If this is a character constant don't try to treat it as a string from
|
||||
* a value_string table. */
|
||||
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, st_arg2, allow_partial_value, NULL);
|
||||
}
|
||||
else {
|
||||
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, st_arg2, allow_partial_value, hfinfo1);
|
||||
}
|
||||
|
@ -660,7 +698,8 @@ check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
|
|||
fvalue = dfilter_fvalue_from_string(dfw, ftype2, st_arg1, hfinfo2);
|
||||
stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
|
||||
type2 == STTYPE_CHARCONST) {
|
||||
/* Well now that's silly... */
|
||||
FAIL(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
|
||||
stnode_todisplay(st_arg1),
|
||||
|
@ -718,7 +757,8 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
|
|||
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, st_arg1, allow_partial_value, hfinfo2);
|
||||
stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
|
||||
type2 == STTYPE_CHARCONST) {
|
||||
/* Well now that's silly... */
|
||||
FAIL(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
|
||||
stnode_todisplay(st_arg1),
|
||||
|
@ -787,6 +827,12 @@ check_relation_LHS_RANGE(dfwork_t *dfw, test_op_t st_op,
|
|||
fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, st_arg2, allow_partial_value, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_CHARCONST) {
|
||||
/* The RHS should be FT_BYTES, but a character is just a
|
||||
* one-byte byte string. */
|
||||
fvalue = dfilter_fvalue_from_charconst_string(dfw, FT_BYTES, st_arg2, allow_partial_value);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_RANGE) {
|
||||
check_drange_sanity(dfw, st_arg2);
|
||||
}
|
||||
|
@ -862,7 +908,7 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op,
|
|||
fvalue = dfilter_fvalue_from_string(dfw, ftype1, st_arg2, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_UNPARSED) {
|
||||
else if (type2 == STTYPE_UNPARSED || type2 == STTYPE_CHARCONST) {
|
||||
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, st_arg2, allow_partial_value, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,15 @@ sttype_register_string(void)
|
|||
string_tostr
|
||||
};
|
||||
|
||||
static sttype_t charconst_type = {
|
||||
STTYPE_CHARCONST,
|
||||
"CHARCONST",
|
||||
NULL,
|
||||
string_free,
|
||||
string_dup,
|
||||
string_tostr
|
||||
};
|
||||
|
||||
static sttype_t unparsed_type = {
|
||||
STTYPE_UNPARSED,
|
||||
"UNPARSED",
|
||||
|
@ -50,6 +59,7 @@ sttype_register_string(void)
|
|||
};
|
||||
|
||||
sttype_register(&string_type);
|
||||
sttype_register(&charconst_type);
|
||||
sttype_register(&unparsed_type);
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,12 @@ stnode_new_unparsed(const char *str)
|
|||
return stnode_new(STTYPE_UNPARSED, g_strdup(str));
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
stnode_new_charconst(const char *str)
|
||||
{
|
||||
return stnode_new(STTYPE_CHARCONST, g_strdup(str));
|
||||
}
|
||||
|
||||
stnode_t*
|
||||
stnode_dup(const stnode_t *node)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ typedef enum {
|
|||
STTYPE_TEST,
|
||||
STTYPE_UNPARSED,
|
||||
STTYPE_STRING,
|
||||
STTYPE_CHARCONST,
|
||||
STTYPE_FIELD,
|
||||
STTYPE_FVALUE,
|
||||
STTYPE_RANGE,
|
||||
|
@ -110,6 +111,9 @@ stnode_new_string(const char *str);
|
|||
stnode_t *
|
||||
stnode_new_unparsed(const char *str);
|
||||
|
||||
stnode_t *
|
||||
stnode_new_charconst(const char *str);
|
||||
|
||||
stnode_t*
|
||||
stnode_dup(const stnode_t *org);
|
||||
|
||||
|
|
|
@ -174,20 +174,6 @@ byte_array_from_unparsed(const char *s, gchar **err_msg)
|
|||
GByteArray *bytes;
|
||||
gboolean res;
|
||||
|
||||
if (s[0] == '\'') {
|
||||
/*
|
||||
* byte array with length 1 represented as a C-style character constant.
|
||||
*/
|
||||
unsigned long value;
|
||||
if (!parse_charconst(s, &value, err_msg))
|
||||
return NULL;
|
||||
ws_assert(value <= UINT8_MAX);
|
||||
uint8_t one_byte = (uint8_t)value;
|
||||
bytes = g_byte_array_new();
|
||||
g_byte_array_append(bytes, &one_byte, 1);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case where the byte string is specified using a one byte
|
||||
* hex literal. We can't allow this for byte strings that are longer
|
||||
|
|
|
@ -48,7 +48,7 @@ get_sinteger(fvalue_t *fv)
|
|||
return fv->value.sinteger;
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
parse_charconst(const char *s, unsigned long *valuep, gchar **err_msg)
|
||||
{
|
||||
const char *cp;
|
||||
|
|
|
@ -106,9 +106,6 @@ void ftype_register_tvbuff(void);
|
|||
GByteArray *
|
||||
byte_array_from_unparsed(const char *s, gchar **err_msg);
|
||||
|
||||
gboolean
|
||||
parse_charconst(const char *s, unsigned long *valuep, gchar **err_msg);
|
||||
|
||||
#endif /* FTYPES_INT_H */
|
||||
|
||||
/*
|
||||
|
|
|
@ -99,3 +99,7 @@ class case_syntax(unittest.TestCase):
|
|||
def test_charconst_bytes_2(self, checkDFilterCount):
|
||||
dfilter = "frame[54] == 'H'"
|
||||
checkDFilterCount(dfilter, 1)
|
||||
|
||||
def test_charconst_invalid(self, checkDFilterFail):
|
||||
dfilter = r"ip.proto == '\Z'"
|
||||
checkDFilterFail(dfilter, "isn't a valid character constant")
|
||||
|
|
Loading…
Reference in New Issue