Skip to content

Commit

Permalink
lexer: Fix multi-line string parsing
Browse files Browse the repository at this point in the history
Multi-line strings were broken by the generic preprocessing support, as
both double and single quoted strings have their own lexing rules, which
take precedence over the "consume preprocessor tokens" lexer rule.

Reported by Dan Pascu
  • Loading branch information
liviuchircu committed Apr 20, 2019
1 parent 9d82861 commit 4b33da6
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 8 deletions.
14 changes: 6 additions & 8 deletions cfg.lex
Expand Up @@ -77,11 +77,6 @@
#define SCRIPTVAR_S 4

#define STR_BUF_ALLOC_UNIT 128
struct str_buf{
char* s;
char* crt;
int left;
};

static int comment_nest=0;
static int state=0;
Expand Down Expand Up @@ -795,7 +790,9 @@ SPACE [ ]
memset(&s_buf, 0, sizeof(s_buf));
return STRING;
}
<STRING2>.|{EAT_ABLE}|{CR} { yymore(); }
<STRING2>.|{EAT_ABLE} { addchar(&s_buf, *yytext); }
<STRING2>{CR} { count(); if (!eatback_pp_tok(&s_buf))
addchar(&s_buf, *yytext); }

<STRING1>\\n { count(); addchar(&s_buf, '\n'); }
<STRING1>\\r { count(); addchar(&s_buf, '\r'); }
Expand All @@ -809,8 +806,9 @@ SPACE [ ]
subst_uri if allowed (although everybody should use '' in subt_uri) */
<STRING1>\\[0-7]{2,3} { count(); addchar(&s_buf,
(char)strtol(yytext+1, 0, 8)); }
<STRING1>\\{CR} { count(); } /* eat escaped CRs */
<STRING1>{CR} { count();addchar(&s_buf, *yytext); }
<STRING1>\\{CR} { count(); eatback_pp_tok(&s_buf); } /* eat escaped CRs */
<STRING1>{CR} { count(); if (!eatback_pp_tok(&s_buf))
addchar(&s_buf, *yytext); }
<STRING1>.|{EAT_ABLE}|{CR} { addchar(&s_buf, *yytext); }


Expand Down
51 changes: 51 additions & 0 deletions cfg_pp.c
Expand Up @@ -366,6 +366,9 @@ int cfg_pop(void)
return -1;
}

/* the file path MUST NOT be freed, as the lexer and parser work in tandem,
* so by this point, there are plenty of structures referencing it */

if (cfg_include_stackp == cfg_include_stack) {
cfg_include_stackp = NULL;
} else {
Expand Down Expand Up @@ -603,3 +606,51 @@ static FILE *exec_preprocessor(FILE *flat_cfg, const char *preproc_cmdline)
fclose(flat_cfg);
return NULL;
}

int eatback_pp_tok(struct str_buf *buf)
{
char *p;
str last_line;

if (!buf->s)
return 0;

for (p = buf->crt - 1; p >= buf->s; p--)
if (*p == '\n') {
p++;
goto match_pp_tok;
}

return 0;

match_pp_tok:
last_line.s = p;
last_line.len = buf->crt - p;

if (last_line.len < 0) {
LM_BUG("negative line len");
return 0;
}

if (last_line.len >= cfgtok_line.len &&
!memcmp(last_line.s, cfgtok_line.s, cfgtok_line.len))
goto clear_last_line;

if (last_line.len >= cfgtok_filebegin.len &&
!memcmp(last_line.s, cfgtok_filebegin.s, cfgtok_filebegin.len))
goto clear_last_line;

if (last_line.len >= cfgtok_fileend.len &&
!memcmp(last_line.s, cfgtok_fileend.s, cfgtok_fileend.len))
goto clear_last_line;

/* don't touch anything, this is an actual script line! */
return 0;

clear_last_line:
LM_DBG("clearing pp token line: '%.*s'\n", (int)(buf->crt - p), p);
buf->left += buf->crt - p;
*p = '\0';
buf->crt = p;
return 1;
}
11 changes: 11 additions & 0 deletions cfg_pp.h
Expand Up @@ -29,11 +29,22 @@

#define CFG_MAX_INCLUDE_DEPTH 20

struct str_buf{
char* s;
char* crt;
int left;
};

int parse_opensips_cfg(const char *cfg_file, const char *preproc_cmdline,
FILE **ret_stream);
int cfg_push(const str *cfg_file);
int cfg_pop(void);
void cfg_dump_context(const char *file, int line, int colstart, int colend);
void cfg_dump_backtrace(void);

/* ultimately helps correctly parse multi-line strings by eating any
* additionally inserted preprocessor directive as the last line of the
* given string buffer */
int eatback_pp_tok(struct str_buf *buf);

#endif /* __OSS_CFG_PP_H__ */

0 comments on commit 4b33da6

Please sign in to comment.