diff options
Diffstat (limited to 'grammar/rainerscript.c')
-rw-r--r-- | grammar/rainerscript.c | 139 |
1 files changed, 80 insertions, 59 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index a7828839..a1de6442 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -854,7 +854,7 @@ nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param, r = doGetInt(valnode, param, val); break; case eCmdHdlrNonNegInt: - r = doGetPositiveInt(valnode, param, val); + r = doGetNonNegInt(valnode, param, val); break; case eCmdHdlrPositiveInt: r = doGetPositiveInt(valnode, param, val); @@ -1259,7 +1259,7 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr) str = (char*) var2CString(&r[0], &bMustFree); matchnbr = (short) var2Number(&r[2], NULL); submatchnbr = (size_t) var2Number(&r[3], NULL); - if(submatchnbr > sizeof(pmatch)/sizeof(regmatch_t)) { + if(submatchnbr >= sizeof(pmatch)/sizeof(regmatch_t)) { DBGPRINTF("re_extract() submatch %d is too large\n", submatchnbr); bHadNoMatch = 1; goto finalize_it; @@ -1307,15 +1307,19 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr) iLenBuf); } +finalize_it: if(bMustFree) free(str); if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr); if(r[3].datatype == 'S') es_deleteStr(r[3].d.estr); -finalize_it: + if(bHadNoMatch) { cnfexprEval(func->expr[4], &r[4], usrptr); estr = var2String(&r[4], &bMustFree); - if(r[4].datatype == 'S') es_deleteStr(r[4].d.estr); + /* Note that we do NOT free the string that was returned/created + * for r[4]. We pass it to the caller, which in turn frees it. + * This saves us doing one unnecessary memory alloc & write. + */ } ret->datatype = 'S'; ret->d.estr = estr; @@ -1355,6 +1359,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) estr = var2String(&r[0], &bMustFree); ret->d.n = es_strlen(estr); if(bMustFree) es_deleteStr(estr); + if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); } ret->datatype = 'N'; break; @@ -2279,7 +2284,8 @@ cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree) free(cstr); break; case S_ACT: - doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable); + doIndent(indent); dbgprintf("ACTION %p [%s:%s]\n", stmt->d.act, + modGetName(stmt->d.act->pMod), stmt->printable); break; case S_IF: doIndent(indent); dbgprintf("IF\n"); @@ -2447,59 +2453,69 @@ cnfstmtNew(unsigned s_type) return cnfstmt; } +void cnfstmtDestructLst(struct cnfstmt *root); + +/* delete a single stmt */ +static void +cnfstmtDestruct(struct cnfstmt *stmt) +{ + switch(stmt->nodetype) { + case S_NOP: + case S_STOP: + break; + case S_CALL: + es_deleteStr(stmt->d.s_call.name); + break; + case S_ACT: + actionDestruct(stmt->d.act); + break; + case S_IF: + cnfexprDestruct(stmt->d.s_if.expr); + if(stmt->d.s_if.t_then != NULL) { + cnfstmtDestructLst(stmt->d.s_if.t_then); + } + if(stmt->d.s_if.t_else != NULL) { + cnfstmtDestructLst(stmt->d.s_if.t_else); + } + break; + case S_SET: + free(stmt->d.s_set.varname); + cnfexprDestruct(stmt->d.s_set.expr); + break; + case S_UNSET: + free(stmt->d.s_set.varname); + break; + case S_PRIFILT: + cnfstmtDestructLst(stmt->d.s_prifilt.t_then); + cnfstmtDestructLst(stmt->d.s_prifilt.t_else); + break; + case S_PROPFILT: + if(stmt->d.s_propfilt.propName != NULL) + es_deleteStr(stmt->d.s_propfilt.propName); + if(stmt->d.s_propfilt.regex_cache != NULL) + rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache); + if(stmt->d.s_propfilt.pCSCompValue != NULL) + cstrDestruct(&stmt->d.s_propfilt.pCSCompValue); + cnfstmtDestructLst(stmt->d.s_propfilt.t_then); + break; + default: + dbgprintf("error: unknown stmt type during destruct %u\n", + (unsigned) stmt->nodetype); + break; + } + free(stmt->printable); + free(stmt); +} + +/* delete a stmt and all others following it */ void -cnfstmtDestruct(struct cnfstmt *root) +cnfstmtDestructLst(struct cnfstmt *root) { struct cnfstmt *stmt, *todel; for(stmt = root ; stmt != NULL ; ) { - switch(stmt->nodetype) { - case S_NOP: - case S_STOP: - break; - case S_CALL: - es_deleteStr(stmt->d.s_call.name); - break; - case S_ACT: - actionDestruct(stmt->d.act); - break; - case S_IF: - cnfexprDestruct(stmt->d.s_if.expr); - if(stmt->d.s_if.t_then != NULL) { - cnfstmtDestruct(stmt->d.s_if.t_then); - } - if(stmt->d.s_if.t_else != NULL) { - cnfstmtDestruct(stmt->d.s_if.t_else); - } - break; - case S_SET: - free(stmt->d.s_set.varname); - cnfexprDestruct(stmt->d.s_set.expr); - break; - case S_UNSET: - free(stmt->d.s_set.varname); - break; - case S_PRIFILT: - cnfstmtDestruct(stmt->d.s_prifilt.t_then); - cnfstmtDestruct(stmt->d.s_prifilt.t_else); - break; - case S_PROPFILT: - if(stmt->d.s_propfilt.propName != NULL) - es_deleteStr(stmt->d.s_propfilt.propName); - if(stmt->d.s_propfilt.regex_cache != NULL) - rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache); - if(stmt->d.s_propfilt.pCSCompValue != NULL) - cstrDestruct(&stmt->d.s_propfilt.pCSCompValue); - cnfstmtDestruct(stmt->d.s_propfilt.t_then); - break; - default: - dbgprintf("error: unknown stmt type during destruct %u\n", - (unsigned) stmt->nodetype); - break; - } - free(stmt->printable); todel = stmt; stmt = stmt->next; - free(todel); + cnfstmtDestruct(todel); } } @@ -2557,14 +2573,15 @@ struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) { struct cnfstmt* cnfstmt; - rsRetVal lRet; if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) { cnfstmt->printable = (uchar*)propfilt; cnfstmt->d.s_propfilt.t_then = t_then; cnfstmt->d.s_propfilt.propName = NULL; cnfstmt->d.s_propfilt.regex_cache = NULL; cnfstmt->d.s_propfilt.pCSCompValue = NULL; - lRet = DecodePropFilter((uchar*)propfilt, cnfstmt); + if(DecodePropFilter((uchar*)propfilt, cnfstmt) != RS_RET_OK) { + cnfstmt->nodetype = S_NOP; /* disable action! */ + } } return cnfstmt; } @@ -2769,7 +2786,7 @@ cnfexprOptimize_CMP_var(struct cnfexpr *expr) parser_errmsg("invalid facility '%s', expression will always " "evaluate to FALSE", cstr); } else { - /* we can acutally optimize! */ + /* we can actually optimize! */ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n"); func = cnffuncNew_prifilt(fac); if(expr->nodetype == CMP_NE) @@ -2848,7 +2865,7 @@ cnfexprOptimize_AND_OR(struct cnfexpr *expr) static inline void cnfexprOptimize_CMPEQ_arr(struct cnfarray *arr) { - DBGPRINTF("optimizer: sorting array for CMP_EQ/NEQ comparison\n"); + DBGPRINTF("optimizer: sorting array of %d members for CMP_EQ/NEQ comparison\n", arr->nmemb); qsort(arr->arr, arr->nmemb, sizeof(es_str_t*), qs_arrcmp); } @@ -2910,10 +2927,14 @@ cnfexprOptimize(struct cnfexpr *expr) expr->r = exprswap; } } + if(expr->r->nodetype == 'A') { + cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r); + } + /* This should be evaluated last because it may change expr + * to a function. + */ if(expr->l->nodetype == 'V') { expr = cnfexprOptimize_CMP_var(expr); - } else if(expr->r->nodetype == 'A') { - cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r); } break; case CMP_LE: @@ -3050,7 +3071,7 @@ cnfstmtOptimizePRIFilt(struct cnfstmt *stmt) DBGPRINTF("optimizer: removing always-true PRIFILT %p\n", stmt); if(stmt->d.s_prifilt.t_else != NULL) { parser_errmsg("error: always-true PRI filter has else part!\n"); - cnfstmtDestruct(stmt->d.s_prifilt.t_else); + cnfstmtDestructLst(stmt->d.s_prifilt.t_else); } free(stmt->printable); stmt->printable = NULL; |