Commit Diff


commit - 86cc2a8811c0ecaa347a5e512ea99e1bd18bda67
commit + c3bc010b87f4bb42e288a001030b71468e4ea051
blob - 129e1591f556a77f2c976bb3b91c4a17977f5dcb
blob + 8f4c3fd4e7d148dca1dfa58ceb3a3dafbb6c0faf
--- pdf.c
+++ pdf.c
@@ -102,7 +102,13 @@ validate_eq_uint(HParseResult *p, void *u)
 	    v->uint == (uint64_t)(uintptr_t)u);
 }
 
+bool
+validate_notnull(HParseResult *p, void *u)
+{
+	return p->ast != NULL;
+}
 
+
 /*
  * auxiliary global data structure needed by the parser
  */
@@ -530,15 +536,23 @@ act_nat(const HParseResult *p, void *u)
 	uint64_t x = 0;
 	HCountedArray *seq = H_CAST_SEQ(p->ast);
 
-	// XXX check for overflow
-	for (size_t i = 0; i < seq->used; i++)
-		x = x*10 + H_CAST_UINT(seq->elements[i]);
+	for (size_t i = 0; i < seq->used; i++) {
+		uint64_t d = H_CAST_UINT(seq->elements[i]);
+
+		if (x > (UINT64_MAX - d) / 10)	/* would overflow */
+			return NULL;
+		// XXX introduce a structured error type and unify with VIOL()
 
+		x = x * 10 + d;
+	}
+
 	return H_MAKE_UINT(x);
 }
 #define act_xroff act_nat
 #define act_xrgen act_nat
 
+#define validate_nat validate_notnull
+
 HParser *p_violsev;
 HParsedToken *
 act_viol(const HParseResult *p, void *viol)
@@ -618,6 +632,8 @@ act_numb(const HParseResult *p, void *u)
 	assert(sgn == 1 || sgn == -1);
 	switch (x->token_type) {
 	case TT_UINT:
+		if (x->uint > -INT64_MIN)	/* would overflow */
+			return NULL;	// XXX structured error type
 		return H_MAKE_SINT(sgn * x->uint);
 	case TT_DOUBLE:
 		return H_MAKE_DOUBLE(sgn * x->dbl);
@@ -626,6 +642,8 @@ act_numb(const HParseResult *p, void *u)
 	}
 }
 
+#define validate_numb validate_notnull
+
 HParsedToken *
 act_ref(const HParseResult *p, void *u)
 {
@@ -951,7 +969,7 @@ init_parser(struct Env *aux)
 	H_RULE(epsilon,	h_epsilon_p());
 	H_RULE(empty,	SEQ(epsilon));
 	H_RULE(digits,	h_many1(digit));
-	H_ARULE(nat,	digits);
+	H_VARULE(nat,	digits);
 	H_VRULE(pnat,	nat);
 	H_RULE(npair,	SEQ(pnat, wel,ws, nat));
 
@@ -972,7 +990,7 @@ init_parser(struct Env *aux)
 		// XXX ^ we _could_ move the "123." case into intnn...
 	H_RULE(numbnn,	CHX(realnn, intnn));
 	H_RULE(snumb,	SEQ(sign, numbnn));
-	H_ARULE(numb,	CHX(snumb, numbnn));
+	H_VARULE(numb,	CHX(snumb, numbnn));
 
 	/* names */
 	H_ARULE(nesc,	SEQ(hash, hdigit, hdigit));