/** * verify_dfa - verify that all the transitions and states in the dfa tables * are in bounds. * @dfa: dfa to test * * assumes dfa has gone through the verification done by unpacking */ int verify_dfa(struct aa_dfa *dfa) { size_t i, state_count, trans_count; int error = -EPROTO; /* check that required tables exist */ if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] && dfa->tables[YYTD_ID_DEF - 1] && dfa->tables[YYTD_ID_BASE - 1] && dfa->tables[YYTD_ID_NXT - 1] && dfa->tables[YYTD_ID_CHK - 1])) goto out; /* accept.size == default.size == base.size */ state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen; if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen && state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen)) goto out; /* next.size == chk.size */ trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen; if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen) goto out; /* if equivalence classes then its table size must be 256 */ if (dfa->tables[YYTD_ID_EC - 1] && dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256) goto out; for (i = 0; i < state_count; i++) { if (DEFAULT_TABLE(dfa)[i] >= state_count) goto out; if (BASE_TABLE(dfa)[i] >= trans_count + 256) goto out; } for (i = 0; i < trans_count ; i++) { if (NEXT_TABLE(dfa)[i] >= state_count) goto out; if (CHECK_TABLE(dfa)[i] >= state_count) goto out; } /* verify accept permissions */ for (i = 0; i < state_count; i++) { int mode = ACCEPT_TABLE(dfa)[i]; if (mode & ~AA_VALID_PERM_MASK) { goto out; } } error = 0; out: return error; }
/** * aa_dfa_matchn_until - traverse @dfa until accept or @n bytes consumed * @dfa: the dfa to match @str against (NOT NULL) * @start: the state of the dfa to start matching in * @str: the string of bytes to match against the dfa (NOT NULL) * @n: length of the string of bytes to match * @retpos: first character in str after match OR str + n * * aa_dfa_match_len will match @str against the dfa and return the state it * finished matching in. The final state can be used to look up the accepting * label, or as the start state of a continuing match. * * This function will happily match again the 0 byte and only finishes * when @n input is consumed. * * Returns: final state reached after input is consumed */ unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start, const char *str, int n, const char **retpos) { u16 *def = DEFAULT_TABLE(dfa); u32 *base = BASE_TABLE(dfa); u16 *next = NEXT_TABLE(dfa); u16 *check = CHECK_TABLE(dfa); u32 *accept = ACCEPT_TABLE(dfa); unsigned int state = start, pos; *retpos = NULL; if (state == 0) return 0; /* current state is <state>, matching character *str */ if (dfa->tables[YYTD_ID_EC]) { /* Equivalence class table defined */ u8 *equiv = EQUIV_TABLE(dfa); /* default is direct to next state */ for (; n; n--) { pos = base_idx(base[state]) + equiv[(u8) *str++]; if (check[pos] == state) state = next[pos]; else state = def[state]; if (accept[state]) break; } } else { /* default is direct to next state */ for (; n; n--) { pos = base_idx(base[state]) + (u8) *str++; if (check[pos] == state) state = next[pos]; else state = def[state]; if (accept[state]) break; } } *retpos = str; return state; }
/** * aa_dfa_match - find accept perm for @str in @dfa * @dfa: the dfa to match @str against * @str: the string to match against the dfa * * aa_dfa_match will match @str and return the accept perms for the * final state. */ unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str) { return ACCEPT_TABLE(dfa)[aa_dfa_next_state(dfa, DFA_START, str)]; }