#include "esi/Expression.h"
#include "esi/Segment.h"
#include "esi/VarState.h"
+#include "FadingCounter.h"
#include "fatal.h"
#include "http/Stream.h"
#include "HttpHdrSc.h"
ESIContext::addStackElement (ESIElement::Pointer element)
{
/* Put on the stack to allow skipping of 'invalid' markup */
- Must(parserState.stackdepth < 10);
+
+ // throw an error if the stack location would be invalid
+ if (parserState.stackdepth >= ESI_STACK_DEPTH_LIMIT)
+ throw Esi::Error("ESI Too many nested elements");
+ if (parserState.stackdepth < 0)
+ throw Esi::Error("ESI elements stack error, probable error in ESI template");
+
assert (!failed());
debugs(86, 5, "ESIContext::addStackElement: About to add ESI Node " << element.getRaw());
if (!parserState.top()->addElement(element)) {
- debugs(86, DBG_IMPORTANT, "ESIContext::addStackElement: failed to add esi node, probable error in ESI template");
- flags.error = 1;
+ throw Esi::Error("ESIContext::addStackElement failed, probable error in ESI template");
} else {
/* added ok, push onto the stack */
parserState.stack[parserState.stackdepth] = element;
assert (len);
debugs(86, 5, "literal length is " << len);
/* give a literal to the current element */
- Must(parserState.stackdepth < 10);
ESIElement::Pointer element (new esiLiteral (this, s, len));
- if (!parserState.top()->addElement(element)) {
- debugs(86, DBG_IMPORTANT, "ESIContext::addLiteral: failed to add esi node, probable error in ESI template");
- flags.error = 1;
- }
+ if (!parserState.top()->addElement(element))
+ throw Esi::Error("ESIContext::addLiteral failed, probable error in ESI template");
}
void
PROF_start(esiParsing);
- while (buffered.getRaw() && !flags.error)
- parseOneBuffer();
+ try {
+ while (buffered.getRaw() && !flags.error)
+ parseOneBuffer();
+
+ } catch (Esi::ErrorDetail &errMsg) { // FIXME: non-const for c_str()
+ // level-2: these are protocol/syntax errors from upstream
+ debugs(86, 2, "WARNING: ESI syntax error: " << errMsg);
+ setError();
+ setErrorMessage(errMsg.c_str());
+
+ } catch (...) {
+ // DBG_IMPORTANT because these are local issues the admin needs to fix
+ static FadingCounter logEntries; // TODO: set horizon less than infinity
+ if (logEntries.count(1) < 100)
+ debugs(86, DBG_IMPORTANT, "ERROR: ESI parser: " << CurrentException);
+ setError();
+ setErrorMessage("ESI parser error");
+ }
PROF_stop(esiParsing);
#include "squid.h"
#include "Debug.h"
+#include "esi/Esi.h"
#include "esi/Expression.h"
#include "profiler/Profiler.h"
cleanmember(&s[*depth]);
}
+static void
+stackpush(stackmember *stack, stackmember &item, int *depth)
+{
+ if (*depth < 0)
+ throw Esi::Error("ESIExpression stack has negative size");
+ if (*depth >= ESI_STACK_DEPTH_LIMIT)
+ throw Esi::Error("ESIExpression stack is full, cannot push");
+
+ stack[(*depth)++] = item;
+}
+
static evaluate evalnegate;
static evaluate evalliteral;
static evaluate evalor;
/* invalid stack */
return 1;
+ if (whereAmI < 0)
+ throw Esi::Error("negate expression location too small");
+ if (*depth >= ESI_STACK_DEPTH_LIMIT)
+ throw Esi::Error("negate expression too complex");
+
if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR)
/* invalid operand */
return 1;
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
srv.precedence = 1;
- stack[(*depth)++] = srv;
+ stackpush(stack, srv, depth);
/* we're out of way, try adding now */
if (!addmember(stack, depth, candidate))
/* !(!(a==b))) is why thats safe */
/* strictly less than until we unwind */
+ if (*stackdepth >= ESI_STACK_DEPTH_LIMIT)
+ throw Esi::Error("ESI expression too complex to add member");
+
if (candidate->precedence < stack[*stackdepth - 1].precedence ||
candidate->precedence < stack[*stackdepth - 2].precedence) {
/* must be an operator */
return 0;
}
} else {
- stack[(*stackdepth)++] = *candidate;
+ stackpush(stack, *candidate, stackdepth);
}
} else if (candidate->valuetype != ESI_EXPR_INVALID)
- stack[(*stackdepth)++] = *candidate;
+ stackpush(stack, *candidate, stackdepth);
return 1;
}
int
ESIExpression::Evaluate(char const *s)
{
- stackmember stack[20];
+ stackmember stack[ESI_STACK_DEPTH_LIMIT];
int stackdepth = 0;
char const *end;
PROF_start(esiExpressionEval);