particle/map: non-greedy matching of quotes

Flex regexps are greedy.

This means '"foo" || "bar"' will return 'foo" || "bar', which is
obviously wrong.

Use "start conditions" to implement non-greedy matching.

Closes #302
This commit is contained in:
Daniel Eklöf 2023-07-24 17:13:19 +02:00
parent 9f5f35a8ac
commit 78f7b60e13
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 58 additions and 1 deletions

View file

@ -19,8 +19,11 @@
### Fixed ### Fixed
* Compiler error _fmt may be used uninitialized_ ([#311][311]). * Compiler error _fmt may be used uninitialized_ ([#311][311]).
* map: conditions failing to match when they contain multiple, quoted
tag values ([#302][302]).
[311]: https://codeberg.org/dnkl/yambar/issues/311 [311]: https://codeberg.org/dnkl/yambar/issues/311
[302]: https://codeberg.org/dnkl/yambar/issues/302
### Security ### Security

View file

@ -2,13 +2,67 @@
#include <string.h> #include <string.h>
#include "map.h" #include "map.h"
#include "map.tab.h" #include "map.tab.h"
void yyerror(const char *s);
%} %}
%option warn nodefault nounput noinput noyywrap %option warn nodefault nounput noinput noyywrap
char *quoted = NULL;
size_t quote_len = 0;
%x QUOTE
%% %%
[[:alnum:]_-]+ yylval.str = strdup(yytext); return WORD; [[:alnum:]_-]+ yylval.str = strdup(yytext); return WORD;
\".*\" yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STRING;
\" {
BEGIN(QUOTE);
quoted = calloc(1, sizeof(quoted[0]));
}
<QUOTE>[^\\\"]* {
/* printf("CAT: %s\n", yytext); */
const size_t yy_length = strlen(yytext);
quoted = realloc(quoted, quote_len + yy_length + 1);
strcat(quoted, yytext);
quote_len += yy_length;
}
<QUOTE>\\\" {
/* printf("escaped quote\n"); */
quoted = realloc(quoted, quote_len + 1 + 1);
strcat(quoted, "\"");
quote_len++;
}
<QUOTE>\\. {
/* printf("CAT: %s\n", yytext); */
const size_t yy_length = strlen(yytext);
quoted = realloc(quoted, quote_len + yy_length + 1);
strcat(quoted, yytext);
quote_len += yy_length;
}
<QUOTE>\\ {
/* quoted string that ends with a backslash: "string\ */
quoted = realloc(quoted, quote_len + 1 + 1);
strcat(quoted, "\\");
quote_len++;
}
<QUOTE>\" {
/* printf("QUOTED=%s\n", quoted); */
yylval.str = strdup(quoted);
free(quoted);
quoted = NULL;
quote_len = 0;
BEGIN(INITIAL);
return STRING;
}
== yylval.op = MAP_OP_EQ; return CMP_OP; == yylval.op = MAP_OP_EQ; return CMP_OP;
!= yylval.op = MAP_OP_NE; return CMP_OP; != yylval.op = MAP_OP_NE; return CMP_OP;
\<= yylval.op = MAP_OP_LE; return CMP_OP; \<= yylval.op = MAP_OP_LE; return CMP_OP;