[Support/GlobPattern] - Do not crash when pattern has characters with int value < 0.

Found it during work on LLD, it would crash on following 
linker script:

SECTIONS { .foo : { *("*®") } }
That happens because ® has int value -82. And chars are used as
array index in code, and are signed by default.

Differential revision: https://reviews.llvm.org/D35891

llvm-svn: 309549
This commit is contained in:
George Rimar 2017-07-31 09:26:50 +00:00
parent e48aac838f
commit cb3a7c1636
2 changed files with 19 additions and 7 deletions

View File

@ -33,27 +33,30 @@ static Expected<BitVector> expand(StringRef S, StringRef Original) {
if (S.size() < 3) if (S.size() < 3)
break; break;
uint8_t Start = S[0];
uint8_t End = S[2];
// If it doesn't start with something like X-Y, // If it doesn't start with something like X-Y,
// consume the first character and proceed. // consume the first character and proceed.
if (S[1] != '-') { if (S[1] != '-') {
BV[S[0]] = true; BV[Start] = true;
S = S.substr(1); S = S.substr(1);
continue; continue;
} }
// It must be in the form of X-Y. // It must be in the form of X-Y.
// Validate it and then interpret the range. // Validate it and then interpret the range.
if (S[0] > S[2]) if (Start > End)
return make_error<StringError>("invalid glob pattern: " + Original, return make_error<StringError>("invalid glob pattern: " + Original,
errc::invalid_argument); errc::invalid_argument);
for (int C = S[0]; C <= S[2]; ++C) for (int C = Start; C <= End; ++C)
BV[C] = true; BV[(uint8_t)C] = true;
S = S.substr(3); S = S.substr(3);
} }
for (char C : S) for (char C : S)
BV[C] = true; BV[(uint8_t)C] = true;
return BV; return BV;
} }
@ -89,7 +92,7 @@ static Expected<BitVector> scan(StringRef &S, StringRef Original) {
} }
default: default:
BitVector BV(256, false); BitVector BV(256, false);
BV[S[0]] = true; BV[(uint8_t)S[0]] = true;
S = S.substr(1); S = S.substr(1);
return BV; return BV;
} }
@ -159,7 +162,7 @@ bool GlobPattern::matchOne(ArrayRef<BitVector> Pats, StringRef S) const {
} }
// If Pats[0] is not '*', it must consume one character. // If Pats[0] is not '*', it must consume one character.
if (S.empty() || !Pats[0][S[0]]) if (S.empty() || !Pats[0][(uint8_t)S[0]])
return false; return false;
Pats = Pats.slice(1); Pats = Pats.slice(1);
S = S.substr(1); S = S.substr(1);

View File

@ -67,4 +67,13 @@ TEST_F(GlobPatternTest, Invalid) {
EXPECT_FALSE((bool)Pat1); EXPECT_FALSE((bool)Pat1);
handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {}); handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {});
} }
TEST_F(GlobPatternTest, ExtSym) {
Expected<GlobPattern> Pat1 = GlobPattern::create("a*\xFF");
EXPECT_TRUE((bool)Pat1);
EXPECT_TRUE(Pat1->match("axxx\xFF"));
Expected<GlobPattern> Pat2 = GlobPattern::create("[\xFF-\xFF]");
EXPECT_TRUE((bool)Pat2);
EXPECT_TRUE(Pat2->match("\xFF"));
}
} }