Commit Diff


commit - b5568c0ce46c37f080fe97f45bfb67e9744e8fde
commit + da562f47c891cc2678b984fafdc886764783bf4b
blob - b8bbb7e80784e56ddb6d2899270662ef980b569a
blob + 8cc9cd17b99a35b19a32ef4eb9f1e5f3676ee54c
--- pdf.c
+++ pdf.c
@@ -2826,10 +2826,11 @@ parse_objstm_obj(struct Env *aux, size_t nr, size_t st
 }
 
 /* resolve a parsed object to its final semantic value */
+	static void *INVALID = &INVALID;	/* a reserved dummy pointer */
+		// XXX move this back into the function
 const HParsedToken *
 resolve(struct Env *aux, const HParsedToken *v)
 {
-	static void *INVALID = &INVALID;	/* a reserved dummy pointer */
 	XREntry *ent = NULL;
 	Ref *r;
 
@@ -3642,9 +3643,8 @@ resolve_item(struct Env *aux, const HParsedToken *v, s
 	XREntry *ent = NULL;
 	Ref *r;
 
-
 	/* the null object maps to NULL */
-	if (v == NULL || v->token_type == TT_Null)
+	if (v == NULL || v == INVALID || v->token_type == TT_Null)
 		return NULL;
 
 	/* other direct objects pass through */
@@ -3662,8 +3662,7 @@ resolve_item(struct Env *aux, const HParsedToken *v, s
 	if (ent->obj != NULL)
 		return resolve_item(aux, ent->obj, offset, p);
 
-	/* parse the object and memoize */
-	ent->obj = v;				/* break loops */
+	/* parse the object */
 	switch (ent->type)
 	{
 	case XR_FREE:
@@ -3671,13 +3670,13 @@ resolve_item(struct Env *aux, const HParsedToken *v, s
 	case XR_INUSE:
 		if (ent->n.gen != r->gen)
 			return NULL;		/* obj nr reused */
-		ent->obj = parse_item(aux, r->nr, r->gen, ent->n.offs, p);
+		v = parse_item(aux, r->nr, r->gen, ent->n.offs, p);
 		*offset = ent->n.offs;
 		break;
 	case XR_OBJSTM:
 		if (r->gen != 0)
 			return NULL;		/* invalid entry! */
-		ent->obj = parse_objstm_item(aux, r->nr, ent->o.stm, ent->o.idx, offset, p);
+		v = parse_objstm_item(aux, r->nr, ent->o.stm, ent->o.idx, offset, p);
 		break;
 	default:
 		/*
@@ -3687,7 +3686,13 @@ resolve_item(struct Env *aux, const HParsedToken *v, s
 		return NULL;
 	}
 
-	return resolve_item(aux, ent->obj, offset, p);
+	/* resolve recursively and memoize */
+	ent->obj = INVALID;			/* break loops */
+	if ((v = resolve_item(aux, v, offset, p)) != NULL)
+		ent->obj = v;
+
+	assert(v != INVALID);			/* our dummy does not escape */
+	return v;
 }