diff --git a/src/smack1.c b/src/smack1.c index 34f72a90a3e1ebed609a4a689212d0d923a26c09..149eceb2c873aede5de60f885e48e8dfb4a1a17b 100644 --- a/src/smack1.c +++ b/src/smack1.c @@ -212,6 +212,8 @@ struct SmackPattern unsigned is_anchor_end:1; unsigned is_snmp_hack:1; + + unsigned is_wildcards:1; }; @@ -673,6 +675,7 @@ smack_add_pattern( pat->is_anchor_begin = ((flags & SMACK_ANCHOR_BEGIN) > 0); pat->is_anchor_end = ((flags & SMACK_ANCHOR_END) > 0); pat->is_snmp_hack = ((flags & SMACK_SNMP_HACK) > 0); + pat->is_wildcards = ((flags & SMACK_WILDCARDS) > 0); pat->id = id; pat->pattern = make_copy_of_pattern(pattern, pattern_length, smack->is_nocase); if (pat->is_anchor_begin) @@ -1050,6 +1053,59 @@ smack_stage3_sort(struct SMACK *smack) smack->m_match_limit = start; } +/**************************************************************************** + * + * KLUDGE KLUDGE KLUDGE KLUDGE KLUDGE + * + * This function currently only works in a very narrow case, for the SMB + * parser, where all the patterns are "anchored" and none overlap with the + * the SMB patterns. This allows us to modify existing states with the + * the wildcards, without adding new states. Do do this right we need + * to duplicate states in order to track wildcards + ****************************************************************************/ +static void +smack_fixup_wildcards(struct SMACK *smack) +{ + size_t i; + + for (i=0; i<smack->m_pattern_count; i++) { + size_t j; + struct SmackPattern *pat = smack->m_pattern_list[i]; + + /* skip patterns that aren't wildcards */ + if (!pat->is_wildcards) + continue; + + /* find the state leading up to the wilcard * character */ + for (j=0; j<pat->pattern_length; j++) { + unsigned row = 0; + unsigned offset = 0; + size_t row_size = (1 << smack->row_shift); + transition_t *table; + transition_t next_pattern; + transition_t base_state = (smack->is_anchor_begin?1:0); + size_t k; + + /* Skip non-wildcard characters */ + if (pat->pattern[j] != '*') + continue; + + /* find the current 'row' */ + while (offset < j) + smack_search_next(smack, &row, pat->pattern, &offset, (unsigned)j); + + row = row & 0xFFFFFF; + table = smack->table + (row << smack->row_shift); + next_pattern = table[smack->char_to_symbol['*']]; + + for (k=0; k<row_size; k++) { + if (table[k] == base_state) + table[k] = next_pattern; + } + } + } + +} /**************************************************************************** ****************************************************************************/ void @@ -1106,12 +1162,18 @@ smack_compile(struct SMACK *smack) swap_rows(smack, BASE_STATE, UNANCHORED_STATE); } + /* prettify table for debugging */ smack_stage3_sort(smack); /* * Build the final table we use for evaluation */ smack_stage4_make_final_table(smack); + + /* + * Fixup the wildcard states + */ + smack_fixup_wildcards(smack); /* * Get rid of the original pattern tables, since we no longer need them.