commit 5278f8f077195cc3da3dacee5b376cdd8e811bb6
parent 8375c04910e59654bc4fee4fbe8a820e1d3f839d
Author: sin <sin@2f30.org>
Date: Thu, 17 Dec 2015 12:38:07 +0000
Do not kill the process if a parsing error occurs
Diffstat:
M | ben.c | | | 55 | +++++++++++++++++++++++++++++++++++++------------------ |
1 file changed, 37 insertions(+), 18 deletions(-)
diff --git a/ben.c b/ben.c
@@ -16,6 +16,7 @@
#include <ctype.h>
#include <err.h>
+#include <setjmp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,6 +24,17 @@
#include "sbtd.h"
+static char *parse(char *, char *, struct ben **);
+
+static jmp_buf savesp;
+
+static void
+error(char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ longjmp(savesp, 1);
+}
+
static char *
parsestr(char *s, char *e, struct ben **b)
{
@@ -32,11 +44,11 @@ parsestr(char *s, char *e, struct ben **b)
for (p = s; p != e && isdigit((int)*p); p++)
len = len * 10 + *p - '0';
if (p == e)
- goto eof;
+ error("bad string");
if (*p != ':')
- errx(1, "expected :, got %c", *p);
+ error("expected ':' in string");
if (p + len >= e)
- goto eof;
+ error("bad string");
p += len;
*b = emalloc(sizeof(**b));
(*b)->type = 's';
@@ -45,8 +57,6 @@ parsestr(char *s, char *e, struct ben **b)
(*b)->end = p + 1;
(*b)->len = len;
return p;
-eof:
- errx(1, "bad string");
}
static char *
@@ -57,9 +67,9 @@ parseint(char *s, char *e, struct ben **b)
int isneg = 0, iszero = 0;
if (*p != 'i')
- errx(1, "expected integer");
+ error("expected integer");
if (++p == e)
- errx(1, "bad integer");
+ error("bad integer");
switch (*p) {
case '-':
@@ -77,16 +87,16 @@ parseint(char *s, char *e, struct ben **b)
v = 0;
while (1) {
if (++p == e)
- errx(1, "bad integer");
+ error("bad integer");
if (*p == 'e' || iszero) {
if (*p != 'e')
- errx(1, "0 not followed by e");
+ error("0 not followed by e");
break;
}
if (isneg && *p == '0')
- errx(1, "i-0 is invalid");
+ error("i-0 is invalid");
if (!isdigit((int)*p))
- errx(1, "unexpected char in integer %c", *p);
+ error("unexpected char in integer");
v = v * 10 + *p - '0';
}
@@ -108,10 +118,10 @@ parsedl(char *s, char *e, struct ben **b)
memset(&head, 0, sizeof(head));
if (*p != 'd' && *p != 'l')
- errx(1, "expected dictionary or list");
+ error("expected dictionary or list");
while (1) {
if (++p == e)
- errx(1, "bad dictionary or list");
+ error("bad dictionary or list");
if (*p == 'e')
break;
bp->next = emalloc(sizeof(*bp));
@@ -122,11 +132,11 @@ parsedl(char *s, char *e, struct ben **b)
p = parsestr(p, e, &bp->k);
p++;
}
- p = bdecode(p, e, &bp->v);
+ p = parse(p, e, &bp->v);
bp->next = NULL;
}
if (*p != 'e')
- errx(1, "expected terminator");
+ error("expected terminator");
*b = head.next;
if (!head.next) {
@@ -141,8 +151,8 @@ parsedl(char *s, char *e, struct ben **b)
return p;
}
-char *
-bdecode(char *s, char *e, struct ben **b)
+static char *
+parse(char *s, char *e, struct ben **b)
{
if (s == e)
return s;
@@ -156,11 +166,20 @@ bdecode(char *s, char *e, struct ben **b)
break;
default:
if (!isdigit((int)*s))
- errx(1, "unknown type %c", *s);
+ error("unknown type");
return parsestr(s, e, b);
}
}
+char *
+bdecode(char *s, char *e, struct ben **b)
+{
+ *b = NULL;
+ if (!setjmp(savesp))
+ return parse(s, e, b);
+ return NULL;
+}
+
void
bencode(char **buf, size_t *n, struct ben *b)
{