#include "logging.h"
#include "regexp.h"
#include "util.h"
#include "walker-inl.h"
namespace lbug {
namespace regex {
static bool CanBeEmptyString(Regexp* re);
class PCREWalker : public Regexp::Walker<bool> {
public:
PCREWalker() {}
virtual bool PostVisit(
Regexp* re, bool parent_arg, bool pre_arg, bool* child_args, int nchild_args);
virtual bool ShortVisit(Regexp* re, bool a) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
LOG(DFATAL) << "PCREWalker::ShortVisit called";
#endif
return a;
}
private:
PCREWalker(const PCREWalker&) = delete;
PCREWalker& operator=(const PCREWalker&) = delete;
};
bool PCREWalker::PostVisit(
Regexp* re, bool parent_arg, bool pre_arg, bool* child_args, int nchild_args) {
for (int i = 0; i < nchild_args; i++)
if (!child_args[i])
return false;
switch (re->op()) {
case kRegexpStar:
case kRegexpPlus:
case kRegexpQuest:
if (CanBeEmptyString(re->sub()[0]))
return false;
break;
case kRegexpRepeat:
if (re->max() == -1 && CanBeEmptyString(re->sub()[0]))
return false;
break;
case kRegexpLiteral:
if (re->rune() == '\v')
return false;
break;
case kRegexpEndText:
case kRegexpEmptyMatch:
if (re->parse_flags() & Regexp::WasDollar)
return false;
break;
case kRegexpBeginLine:
return false;
default:
break;
}
return true;
}
bool Regexp::MimicsPCRE() {
PCREWalker w;
return w.Walk(this, true);
}
class EmptyStringWalker : public Regexp::Walker<bool> {
public:
EmptyStringWalker() {}
virtual bool PostVisit(
Regexp* re, bool parent_arg, bool pre_arg, bool* child_args, int nchild_args);
virtual bool ShortVisit(Regexp* re, bool a) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
LOG(DFATAL) << "EmptyStringWalker::ShortVisit called";
#endif
return a;
}
private:
EmptyStringWalker(const EmptyStringWalker&) = delete;
EmptyStringWalker& operator=(const EmptyStringWalker&) = delete;
};
bool EmptyStringWalker::PostVisit(
Regexp* re, bool parent_arg, bool pre_arg, bool* child_args, int nchild_args) {
switch (re->op()) {
case kRegexpNoMatch: case kRegexpLiteral:
case kRegexpAnyChar:
case kRegexpAnyByte:
case kRegexpCharClass:
case kRegexpLiteralString:
return false;
case kRegexpEmptyMatch: case kRegexpBeginLine: case kRegexpEndLine:
case kRegexpNoWordBoundary:
case kRegexpWordBoundary:
case kRegexpBeginText:
case kRegexpEndText:
case kRegexpStar: case kRegexpQuest:
case kRegexpHaveMatch:
return true;
case kRegexpConcat: for (int i = 0; i < nchild_args; i++)
if (!child_args[i])
return false;
return true;
case kRegexpAlternate: for (int i = 0; i < nchild_args; i++)
if (child_args[i])
return true;
return false;
case kRegexpPlus: case kRegexpCapture:
return child_args[0];
case kRegexpRepeat: return child_args[0] || re->min() == 0;
}
return false;
}
static bool CanBeEmptyString(Regexp* re) {
EmptyStringWalker w;
return w.Walk(re, true);
}
} }