commit 0c3bba0c39399ed5f4beeb9ebb0727dd6d93b329
parent 706b901d7969c3000fac48659de8bb99ff117d62
Author: nibo <nibo@relim.de>
Date: Mon, 14 Oct 2024 10:55:53 +0200
Add more parser restrictions
Diffstat:
| M | chordpro.c | | | 77 | ++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
1 file changed, 48 insertions(+), 29 deletions(-)
diff --git a/chordpro.c b/chordpro.c
@@ -333,14 +333,9 @@ cho_log(enum LogLevel level, const char *msg, ...)
static inline bool
is_whitespace(char c)
{
- if (
- c == '\t' ||
- c == '\n' ||
- c == '\f' ||
- c == '\r' ||
- c == ' '
- )
+ if (c == '\t' || c == ' ') {
return true;
+ }
return false;
}
@@ -2615,7 +2610,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
char directive_name[128];
char directive_value[128];
char chord[15];
- char tag_begin[6];
+ char tag_start[6];
char tag_end[6];
char custom_directive[64];
char *label;
@@ -2707,6 +2702,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
te--;
break;
}
+ if (ta > -1 && !tags[ta]->is_closed) {
+ cho_log(LOG_ERR, "Tag has to be closed on same line.");
+ return NULL;
+ }
songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char));
songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0;
if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) {
@@ -2966,7 +2965,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
if (buf == '{') {
- cho_log(LOG_ERR, "Can't start a new directive if the previous one is not closed yet.");
+ cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
if (buf == '\n') {
@@ -3240,7 +3239,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
if (buf == '{') {
- cho_log(LOG_ERR, "Can't start a new directive if the previous one is not closed yet.");
+ cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
if (buf == '\n') {
@@ -3297,6 +3296,14 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
state = STATE_ANNOTATION;
break;
}
+ if (buf == '\n') {
+ cho_log(LOG_ERR, "Newline character inside a chord is invalid.");
+ return NULL;
+ }
+ if (buf == '[') {
+ cho_log(LOG_ERR, "Can't start a new chord/annotation if the previous one is not yet closed.");
+ return NULL;
+ }
if (buf == '<') {
if (prev_buf == '[') {
songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
@@ -3338,6 +3345,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
state = STATE_MARKUP_TAG;
break;
}
+ if (buf == '\n') {
+ cho_log(LOG_ERR, "Newline character inside an annotation is invalid.");
+ return NULL;
+ }
songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = realloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = buf;
ann++;
@@ -3345,10 +3356,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case STATE_MARKUP_TAG_BEGIN:
MARKUP_TAG_BEGIN:
if (buf == '>') {
- tag_begin[t] = 0;
+ tag_start[t] = 0;
t = 0;
- tags[ta]->name = strdup(tag_begin);
- tag_style = cho_style_parse(tag_begin, NULL, cho_tag_style_inherit(tags, ta-1));
+ tags[ta]->name = strdup(tag_start);
+ tag_style = cho_style_parse(tag_start, NULL, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
@@ -3371,14 +3382,14 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]);
return NULL;
}
- memset(tag_begin, 0, strlen(tag_begin));
+ memset(tag_start, 0, strlen(tag_start));
state = prev_state;
break;
}
if (is_whitespace(buf)) {
- tag_begin[t] = 0;
+ tag_start[t] = 0;
t = 0;
- tags[ta]->name = strdup(tag_begin);
+ tags[ta]->name = strdup(tag_start);
tags[ta]->attrs = realloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *));
tags[ta]->attrs[at] = cho_tag_attr_new();
state = STATE_MARKUP_ATTR_NAME;
@@ -3392,7 +3403,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
cho_log(LOG_ERR, "Begin tag name is too long.");
return NULL;
}
- tag_begin[t] = buf;
+ tag_start[t] = buf;
t++;
break;
case STATE_MARKUP_TAG:
@@ -3418,6 +3429,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
state = prev_state;
break;
}
+ if (buf == '\n') {
+ cho_log(LOG_ERR, "Newline character inside a tag name is invalid.");
+ return NULL;
+ }
if (t == 5) {
cho_log(LOG_ERR, "End tag name is too long.");
return NULL;
@@ -3440,7 +3455,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
} else {
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
return NULL;
}
}
@@ -3452,14 +3467,14 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
return NULL;
}
if (buf == '>') {
if (tags[ta]->attrs[at-1]->value) {
cho_tag_attr_free(tags[ta]->attrs[at]);
tags[ta]->attrs[at] = NULL;
- tag_style = cho_style_parse(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
+ tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
@@ -3483,29 +3498,37 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
return NULL;
}
at = 0;
- memset(tag_begin, 0, strlen(tag_begin));
+ memset(tag_start, 0, strlen(tag_start));
state = prev_state;
break;
} else {
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
atn = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
return NULL;
}
}
+ if (buf == '\n') {
+ cho_log(LOG_ERR, "Newline character inside an tag attribute name is invalid.");
+ return NULL;
+ }
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = buf;
atn++;
break;
case STATE_MARKUP_ATTR_VALUE:
+ if (buf == '\n') {
+ cho_log(LOG_ERR, "Newline character inside an attribute value is invalid.");
+ return NULL;
+ }
if (avs == AVS_NO) {
if (is_whitespace(buf)) {
cho_log(LOG_ERR, "Whitespace character after equals sign is invalid.");
return NULL;
}
if (buf == '>') {
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
return NULL;
}
if (buf == '\'') {
@@ -3520,10 +3543,6 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
break;
}
- if (buf == '\n') {
- cho_log(LOG_ERR, "Newline character inside an attribute value is invalid.");
- return NULL;
- }
if (avs == AVS_UNQUOTED && buf == '>') {
tags[ta]->attrs[at]->value = realloc(tags[ta]->attrs[at]->value, (atv+1) * sizeof(char));
tags[ta]->attrs[at]->value[atv] = 0;
@@ -3531,7 +3550,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
at++;
tags[ta]->attrs = realloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *));
tags[ta]->attrs[at] = NULL;
- tag_style = cho_style_parse(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
+ tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
@@ -3556,7 +3575,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
at = 0;
avs = AVS_NO;
- memset(tag_begin, 0, strlen(tag_begin));
+ memset(tag_start, 0, strlen(tag_start));
state = prev_state;
break;
}