summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libass/ass_drawing.c78
1 files changed, 49 insertions, 29 deletions
diff --git a/libass/ass_drawing.c b/libass/ass_drawing.c
index dd26601..a4ed04c 100644
--- a/libass/ass_drawing.c
+++ b/libass/ass_drawing.c
@@ -43,19 +43,32 @@ static bool token_check_values(ASS_DrawingToken *token, int i, ASS_TokenType typ
return true;
}
-static inline void add_node(ASS_DrawingToken **tail, ASS_TokenType type, ASS_Vector point)
+/*
+ * \brief Free a list of tokens
+ */
+static void drawing_free_tokens(ASS_DrawingToken *token)
+{
+ while (token) {
+ ASS_DrawingToken *at = token;
+ token = token->next;
+ free(at);
+ }
+}
+
+static inline bool add_node(ASS_DrawingToken **tail, ASS_TokenType type, ASS_Vector point)
{
assert(tail && *tail);
ASS_DrawingToken *new_tail = malloc(sizeof(**tail));
if (!new_tail)
- return;
+ return false;
(*tail)->next = new_tail;
new_tail->prev = *tail;
new_tail->next = NULL;
new_tail->type = type;
new_tail->point = point;
*tail = new_tail;
+ return true;
}
static inline bool get_point(const char **str, ASS_Vector *point)
@@ -72,9 +85,10 @@ static inline bool get_point(const char **str, ASS_Vector *point)
* Parses and advances the string for exactly 3 points.
* If the string contains fewer than 3 points,
* any initial matching coordinates are still consumed.
+ * If an allocation fails, error will be set to true.
* \return whether three valid points were added
*/
-static bool add_3_points(const char **str, ASS_DrawingToken **tail, ASS_TokenType type)
+static bool add_3_points(const char **str, ASS_DrawingToken **tail, ASS_TokenType type, bool *error)
{
ASS_Vector buf[3];
@@ -88,9 +102,13 @@ static bool add_3_points(const char **str, ASS_DrawingToken **tail, ASS_TokenTyp
if (!valid)
return false;
- add_node(tail, type, buf[0]);
- add_node(tail, type, buf[1]);
- add_node(tail, type, buf[2]);
+ valid = add_node(tail, type, buf[0]);
+ valid = valid && add_node(tail, type, buf[1]);
+ valid = valid && add_node(tail, type, buf[2]);
+ if (!valid) {
+ *error = true;
+ return false;
+ }
return true;
}
@@ -99,10 +117,11 @@ static bool add_3_points(const char **str, ASS_DrawingToken **tail, ASS_TokenTyp
* Parses and advances the string while it matches points.
* Each set of batch_size points will be turned into tokens and appended to tail.
* Partial matches (i.e. an insufficient amount of coordinates) are still consumed.
+ * If an allocation fails, error will be set to true.
* \return count of added points
*/
static size_t add_many_points(const char **str, ASS_DrawingToken **tail,
- ASS_TokenType type, size_t batch_size)
+ ASS_TokenType type, size_t batch_size, bool *error)
{
ASS_Vector buf[3];
size_t max_buf = sizeof(buf) / sizeof(*buf);
@@ -125,7 +144,10 @@ static size_t add_many_points(const char **str, ASS_DrawingToken **tail,
continue;
for (size_t i = 0; i < count_batch; i++)
- add_node(tail, type, buf[i]);
+ if (!add_node(tail, type, buf[i])) {
+ *error = true;
+ return count_total - count_batch + i;
+ }
count_batch = 0;
}
@@ -154,6 +176,7 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
ASS_DrawingToken *root = NULL, *tail = NULL, *spline_start = NULL;
size_t points = 0;
bool m_seen = false;
+ bool error = false;
while (p && *p) {
char cmd = *p;
@@ -177,9 +200,9 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
if (!get_point(&p, &point))
continue;
if (!add_root_node(&root, &tail, &points, point, TOKEN_MOVE))
- continue;
+ return NULL;
}
- points += add_many_points(&p, &tail, TOKEN_MOVE, 1);
+ points += add_many_points(&p, &tail, TOKEN_MOVE, 1, &error);
break;
case 'n':
if (!root) {
@@ -189,19 +212,19 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
if (!m_seen)
return NULL;
if (!add_root_node(&root, &tail, &points, point, TOKEN_MOVE_NC))
- continue;
+ return NULL;
}
- points += add_many_points(&p, &tail, TOKEN_MOVE_NC, 1);
+ points += add_many_points(&p, &tail, TOKEN_MOVE_NC, 1, &error);
break;
case 'l':
if (!root)
continue;
- points += add_many_points(&p, &tail, TOKEN_LINE, 1);
+ points += add_many_points(&p, &tail, TOKEN_LINE, 1, &error);
break;
case 'b':
if (!root)
continue;
- points += add_many_points(&p, &tail, TOKEN_CUBIC_BEZIER, 3);
+ points += add_many_points(&p, &tail, TOKEN_CUBIC_BEZIER, 3, &error);
break;
case 's':
if (!root)
@@ -209,9 +232,9 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
// Only the initial 3 points are TOKEN_B_SPLINE,
// all following ones are TOKEN_EXTEND_SPLINE
spline_start = tail;
- if (!add_3_points(&p, &tail, TOKEN_B_SPLINE)) {
+ if (!add_3_points(&p, &tail, TOKEN_B_SPLINE, &error)) {
spline_start = NULL;
- continue;
+ break;
}
points += 3;
//-fallthrough
@@ -219,7 +242,7 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
if (points < 3)
continue;
// XXX: use TOKEN_EXTEND_SPLINE
- points += add_many_points(&p, &tail, TOKEN_B_SPLINE, 1);
+ points += add_many_points(&p, &tail, TOKEN_B_SPLINE, 1, &error);
break;
case 'c':
if (!spline_start)
@@ -227,7 +250,10 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
// Close b-splines: add the first three points of the b-spline back to the end
for (int i = 0; i < 3; i++) {
// XXX: use TOKEN_EXTEND_SPLINE
- add_node(&tail, TOKEN_B_SPLINE, spline_start->point);
+ if (!add_node(&tail, TOKEN_B_SPLINE, spline_start->point)) {
+ error = true;
+ break;
+ }
spline_start = spline_start->next;
}
spline_start = NULL;
@@ -236,21 +262,15 @@ static ASS_DrawingToken *drawing_tokenize(const char *str)
// Ignore, just search for next valid command
break;
}
+ if (error)
+ goto fail;
}
return root;
-}
-/*
- * \brief Free a list of tokens
- */
-static void drawing_free_tokens(ASS_DrawingToken *token)
-{
- while (token) {
- ASS_DrawingToken *at = token;
- token = token->next;
- free(at);
- }
+fail:
+ drawing_free_tokens(root);
+ return NULL;
}
/*