1 // Copyright 2003-2009 Google Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This is a variant of PCRE's pcrecpp.cc, originally written at Google. 6 // The main changes are the addition of the HitLimit method and 7 // compilation as PCRE in namespace re2. 8 9 #include <errno.h> 10 #include "util/util.h" 11 #include "util/flags.h" 12 #include "util/pcre.h" 13 14 #define PCREPORT(level) LOG(level) 15 16 // Default PCRE limits. 17 // Defaults chosen to allow a plausible amount of CPU and 18 // not exceed main thread stacks. Note that other threads 19 // often have smaller stacks, and therefore tightening 20 // regexp_stack_limit may frequently be necessary. 21 DEFINE_int32(regexp_stack_limit, 256<<10, "default PCRE stack limit (bytes)"); 22 DEFINE_int32(regexp_match_limit, 1000000, 23 "default PCRE match limit (function calls)"); 24 25 namespace re2 { 26 27 // Maximum number of args we can set 28 static const int kMaxArgs = 16; 29 static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace 30 31 // Approximate size of a recursive invocation of PCRE's 32 // internal "match()" frame. This varies depending on the 33 // compiler and architecture, of course, so the constant is 34 // just a conservative estimate. To find the exact number, 35 // run regexp_unittest with --regexp_stack_limit=0 under 36 // a debugger and look at the frames when it crashes. 37 // The exact frame size was 656 in production on 2008/02/03. 38 static const int kPCREFrameSize = 700; 39 40 // Special name for missing C++ arguments. 41 PCRE::Arg PCRE::no_more_args((void*)NULL); 42 43 const PCRE::PartialMatchFunctor PCRE::PartialMatch = { }; 44 const PCRE::FullMatchFunctor PCRE::FullMatch = { } ; 45 const PCRE::ConsumeFunctor PCRE::Consume = { }; 46 const PCRE::FindAndConsumeFunctor PCRE::FindAndConsume = { }; 47 48 // If a regular expression has no error, its error_ field points here 49 static const string empty_string; 50 51 void PCRE::Init(const char* pattern, Option options, int match_limit, 52 int stack_limit, bool report_errors) { 53 pattern_ = pattern; 54 options_ = options; 55 match_limit_ = match_limit; 56 stack_limit_ = stack_limit; 57 hit_limit_ = false; 58 error_ = &empty_string; 59 report_errors_ = report_errors; 60 re_full_ = NULL; 61 re_partial_ = NULL; 62 63 if (options & ~(EnabledCompileOptions | EnabledExecOptions)) { 64 error_ = new string("illegal regexp option"); 65 PCREPORT(ERROR) 66 << "Error compiling '" << pattern << "': illegal regexp option"; 67 } else { 68 re_partial_ = Compile(UNANCHORED); 69 if (re_partial_ != NULL) { 70 re_full_ = Compile(ANCHOR_BOTH); 71 } 72 } 73 } 74 75 PCRE::PCRE(const char* pattern) { 76 Init(pattern, None, 0, 0, true); 77 } 78 PCRE::PCRE(const char* pattern, Option option) { 79 Init(pattern, option, 0, 0, true); 80 } 81 PCRE::PCRE(const string& pattern) { 82 Init(pattern.c_str(), None, 0, 0, true); 83 } 84 PCRE::PCRE(const string& pattern, Option option) { 85 Init(pattern.c_str(), option, 0, 0, true); 86 } 87 PCRE::PCRE(const string& pattern, const PCRE_Options& re_option) { 88 Init(pattern.c_str(), re_option.option(), re_option.match_limit(), 89 re_option.stack_limit(), re_option.report_errors()); 90 } 91 92 PCRE::PCRE(const char *pattern, const PCRE_Options& re_option) { 93 Init(pattern, re_option.option(), re_option.match_limit(), 94 re_option.stack_limit(), re_option.report_errors()); 95 } 96 97 PCRE::~PCRE() { 98 if (re_full_ != NULL) pcre_free(re_full_); 99 if (re_partial_ != NULL) pcre_free(re_partial_); 100 if (error_ != &empty_string) delete error_; 101 } 102 103 pcre* PCRE::Compile(Anchor anchor) { 104 // Special treatment for anchoring. This is needed because at 105 // runtime pcre only provides an option for anchoring at the 106 // beginning of a string. 107 // 108 // There are three types of anchoring we want: 109 // UNANCHORED Compile the original pattern, and use 110 // a pcre unanchored match. 111 // ANCHOR_START Compile the original pattern, and use 112 // a pcre anchored match. 113 // ANCHOR_BOTH Tack a "\z" to the end of the original pattern 114 // and use a pcre anchored match. 115 116 const char* error; 117 int eoffset; 118 pcre* re; 119 if (anchor != ANCHOR_BOTH) { 120 re = pcre_compile(pattern_.c_str(), 121 (options_ & EnabledCompileOptions), 122 &error, &eoffset, NULL); 123 } else { 124 // Tack a '\z' at the end of PCRE. Parenthesize it first so that 125 // the '\z' applies to all top-level alternatives in the regexp. 126 string wrapped = "(?:"; // A non-counting grouping operator 127 wrapped += pattern_; 128 wrapped += ")\\z"; 129 re = pcre_compile(wrapped.c_str(), 130 (options_ & EnabledCompileOptions), 131 &error, &eoffset, NULL); 132 } 133 if (re == NULL) { 134 if (error_ == &empty_string) error_ = new string(error); 135 PCREPORT(ERROR) << "Error compiling '" << pattern_ << "': " << error; 136 } 137 return re; 138 } 139 140 /***** Convenience interfaces *****/ 141 142 bool PCRE::FullMatchFunctor::operator ()(const StringPiece& text, 143 const PCRE& re, 144 const Arg& a0, 145 const Arg& a1, 146 const Arg& a2, 147 const Arg& a3, 148 const Arg& a4, 149 const Arg& a5, 150 const Arg& a6, 151 const Arg& a7, 152 const Arg& a8, 153 const Arg& a9, 154 const Arg& a10, 155 const Arg& a11, 156 const Arg& a12, 157 const Arg& a13, 158 const Arg& a14, 159 const Arg& a15) const { 160 const Arg* args[kMaxArgs]; 161 int n = 0; 162 if (&a0 == &no_more_args) goto done; args[n++] = &a0; 163 if (&a1 == &no_more_args) goto done; args[n++] = &a1; 164 if (&a2 == &no_more_args) goto done; args[n++] = &a2; 165 if (&a3 == &no_more_args) goto done; args[n++] = &a3; 166 if (&a4 == &no_more_args) goto done; args[n++] = &a4; 167 if (&a5 == &no_more_args) goto done; args[n++] = &a5; 168 if (&a6 == &no_more_args) goto done; args[n++] = &a6; 169 if (&a7 == &no_more_args) goto done; args[n++] = &a7; 170 if (&a8 == &no_more_args) goto done; args[n++] = &a8; 171 if (&a9 == &no_more_args) goto done; args[n++] = &a9; 172 if (&a10 == &no_more_args) goto done; args[n++] = &a10; 173 if (&a11 == &no_more_args) goto done; args[n++] = &a11; 174 if (&a12 == &no_more_args) goto done; args[n++] = &a12; 175 if (&a13 == &no_more_args) goto done; args[n++] = &a13; 176 if (&a14 == &no_more_args) goto done; args[n++] = &a14; 177 if (&a15 == &no_more_args) goto done; args[n++] = &a15; 178 done: 179 180 int consumed; 181 int vec[kVecSize]; 182 return re.DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); 183 } 184 185 bool PCRE::PartialMatchFunctor::operator ()(const StringPiece& text, 186 const PCRE& re, 187 const Arg& a0, 188 const Arg& a1, 189 const Arg& a2, 190 const Arg& a3, 191 const Arg& a4, 192 const Arg& a5, 193 const Arg& a6, 194 const Arg& a7, 195 const Arg& a8, 196 const Arg& a9, 197 const Arg& a10, 198 const Arg& a11, 199 const Arg& a12, 200 const Arg& a13, 201 const Arg& a14, 202 const Arg& a15) const { 203 const Arg* args[kMaxArgs]; 204 int n = 0; 205 if (&a0 == &no_more_args) goto done; args[n++] = &a0; 206 if (&a1 == &no_more_args) goto done; args[n++] = &a1; 207 if (&a2 == &no_more_args) goto done; args[n++] = &a2; 208 if (&a3 == &no_more_args) goto done; args[n++] = &a3; 209 if (&a4 == &no_more_args) goto done; args[n++] = &a4; 210 if (&a5 == &no_more_args) goto done; args[n++] = &a5; 211 if (&a6 == &no_more_args) goto done; args[n++] = &a6; 212 if (&a7 == &no_more_args) goto done; args[n++] = &a7; 213 if (&a8 == &no_more_args) goto done; args[n++] = &a8; 214 if (&a9 == &no_more_args) goto done; args[n++] = &a9; 215 if (&a10 == &no_more_args) goto done; args[n++] = &a10; 216 if (&a11 == &no_more_args) goto done; args[n++] = &a11; 217 if (&a12 == &no_more_args) goto done; args[n++] = &a12; 218 if (&a13 == &no_more_args) goto done; args[n++] = &a13; 219 if (&a14 == &no_more_args) goto done; args[n++] = &a14; 220 if (&a15 == &no_more_args) goto done; args[n++] = &a15; 221 done: 222 223 int consumed; 224 int vec[kVecSize]; 225 return re.DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); 226 } 227 228 bool PCRE::ConsumeFunctor::operator ()(StringPiece* input, 229 const PCRE& pattern, 230 const Arg& a0, 231 const Arg& a1, 232 const Arg& a2, 233 const Arg& a3, 234 const Arg& a4, 235 const Arg& a5, 236 const Arg& a6, 237 const Arg& a7, 238 const Arg& a8, 239 const Arg& a9, 240 const Arg& a10, 241 const Arg& a11, 242 const Arg& a12, 243 const Arg& a13, 244 const Arg& a14, 245 const Arg& a15) const { 246 const Arg* args[kMaxArgs]; 247 int n = 0; 248 if (&a0 == &no_more_args) goto done; args[n++] = &a0; 249 if (&a1 == &no_more_args) goto done; args[n++] = &a1; 250 if (&a2 == &no_more_args) goto done; args[n++] = &a2; 251 if (&a3 == &no_more_args) goto done; args[n++] = &a3; 252 if (&a4 == &no_more_args) goto done; args[n++] = &a4; 253 if (&a5 == &no_more_args) goto done; args[n++] = &a5; 254 if (&a6 == &no_more_args) goto done; args[n++] = &a6; 255 if (&a7 == &no_more_args) goto done; args[n++] = &a7; 256 if (&a8 == &no_more_args) goto done; args[n++] = &a8; 257 if (&a9 == &no_more_args) goto done; args[n++] = &a9; 258 if (&a10 == &no_more_args) goto done; args[n++] = &a10; 259 if (&a11 == &no_more_args) goto done; args[n++] = &a11; 260 if (&a12 == &no_more_args) goto done; args[n++] = &a12; 261 if (&a13 == &no_more_args) goto done; args[n++] = &a13; 262 if (&a14 == &no_more_args) goto done; args[n++] = &a14; 263 if (&a15 == &no_more_args) goto done; args[n++] = &a15; 264 done: 265 266 int consumed; 267 int vec[kVecSize]; 268 if (pattern.DoMatchImpl(*input, ANCHOR_START, &consumed, 269 args, n, vec, kVecSize)) { 270 input->remove_prefix(consumed); 271 return true; 272 } else { 273 return false; 274 } 275 } 276 277 bool PCRE::FindAndConsumeFunctor::operator ()(StringPiece* input, 278 const PCRE& pattern, 279 const Arg& a0, 280 const Arg& a1, 281 const Arg& a2, 282 const Arg& a3, 283 const Arg& a4, 284 const Arg& a5, 285 const Arg& a6, 286 const Arg& a7, 287 const Arg& a8, 288 const Arg& a9, 289 const Arg& a10, 290 const Arg& a11, 291 const Arg& a12, 292 const Arg& a13, 293 const Arg& a14, 294 const Arg& a15) const { 295 const Arg* args[kMaxArgs]; 296 int n = 0; 297 if (&a0 == &no_more_args) goto done; args[n++] = &a0; 298 if (&a1 == &no_more_args) goto done; args[n++] = &a1; 299 if (&a2 == &no_more_args) goto done; args[n++] = &a2; 300 if (&a3 == &no_more_args) goto done; args[n++] = &a3; 301 if (&a4 == &no_more_args) goto done; args[n++] = &a4; 302 if (&a5 == &no_more_args) goto done; args[n++] = &a5; 303 if (&a6 == &no_more_args) goto done; args[n++] = &a6; 304 if (&a7 == &no_more_args) goto done; args[n++] = &a7; 305 if (&a8 == &no_more_args) goto done; args[n++] = &a8; 306 if (&a9 == &no_more_args) goto done; args[n++] = &a9; 307 if (&a10 == &no_more_args) goto done; args[n++] = &a10; 308 if (&a11 == &no_more_args) goto done; args[n++] = &a11; 309 if (&a12 == &no_more_args) goto done; args[n++] = &a12; 310 if (&a13 == &no_more_args) goto done; args[n++] = &a13; 311 if (&a14 == &no_more_args) goto done; args[n++] = &a14; 312 if (&a15 == &no_more_args) goto done; args[n++] = &a15; 313 done: 314 315 int consumed; 316 int vec[kVecSize]; 317 if (pattern.DoMatchImpl(*input, UNANCHORED, &consumed, 318 args, n, vec, kVecSize)) { 319 input->remove_prefix(consumed); 320 return true; 321 } else { 322 return false; 323 } 324 } 325 326 bool PCRE::Replace(string *str, 327 const PCRE& pattern, 328 const StringPiece& rewrite) { 329 int vec[kVecSize]; 330 int matches = pattern.TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize); 331 if (matches == 0) 332 return false; 333 334 string s; 335 if (!pattern.Rewrite(&s, rewrite, *str, vec, matches)) 336 return false; 337 338 assert(vec[0] >= 0); 339 assert(vec[1] >= 0); 340 str->replace(vec[0], vec[1] - vec[0], s); 341 return true; 342 } 343 344 int PCRE::GlobalReplace(string *str, 345 const PCRE& pattern, 346 const StringPiece& rewrite) { 347 int count = 0; 348 int vec[kVecSize]; 349 string out; 350 int start = 0; 351 bool last_match_was_empty_string = false; 352 353 for (; start <= str->length();) { 354 // If the previous match was for the empty string, we shouldn't 355 // just match again: we'll match in the same way and get an 356 // infinite loop. Instead, we do the match in a special way: 357 // anchored -- to force another try at the same position -- 358 // and with a flag saying that this time, ignore empty matches. 359 // If this special match returns, that means there's a non-empty 360 // match at this position as well, and we can continue. If not, 361 // we do what perl does, and just advance by one. 362 // Notice that perl prints '@@@' for this; 363 // perl -le '$_ = "aa"; s/b*|aa/@/g; print' 364 int matches; 365 if (last_match_was_empty_string) { 366 matches = pattern.TryMatch(*str, start, ANCHOR_START, false, 367 vec, kVecSize); 368 if (matches <= 0) { 369 if (start < str->length()) 370 out.push_back((*str)[start]); 371 start++; 372 last_match_was_empty_string = false; 373 continue; 374 } 375 } else { 376 matches = pattern.TryMatch(*str, start, UNANCHORED, true, vec, kVecSize); 377 if (matches <= 0) 378 break; 379 } 380 int matchstart = vec[0], matchend = vec[1]; 381 assert(matchstart >= start); 382 assert(matchend >= matchstart); 383 384 out.append(*str, start, matchstart - start); 385 pattern.Rewrite(&out, rewrite, *str, vec, matches); 386 start = matchend; 387 count++; 388 last_match_was_empty_string = (matchstart == matchend); 389 } 390 391 if (count == 0) 392 return 0; 393 394 if (start < str->length()) 395 out.append(*str, start, str->length() - start); 396 swap(out, *str); 397 return count; 398 } 399 400 bool PCRE::Extract(const StringPiece &text, 401 const PCRE& pattern, 402 const StringPiece &rewrite, 403 string *out) { 404 int vec[kVecSize]; 405 int matches = pattern.TryMatch(text, 0, UNANCHORED, true, vec, kVecSize); 406 if (matches == 0) 407 return false; 408 out->clear(); 409 return pattern.Rewrite(out, rewrite, text, vec, matches); 410 } 411 412 string PCRE::QuoteMeta(const StringPiece& unquoted) { 413 string result; 414 result.reserve(unquoted.size() << 1); 415 416 // Escape any ascii character not in [A-Za-z_0-9]. 417 // 418 // Note that it's legal to escape a character even if it has no 419 // special meaning in a regular expression -- so this function does 420 // that. (This also makes it identical to the perl function of the 421 // same name except for the null-character special case; 422 // see `perldoc -f quotemeta`.) 423 for (int ii = 0; ii < unquoted.length(); ++ii) { 424 // Note that using 'isalnum' here raises the benchmark time from 425 // 32ns to 58ns: 426 if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') && 427 (unquoted[ii] < 'A' || unquoted[ii] > 'Z') && 428 (unquoted[ii] < '0' || unquoted[ii] > '9') && 429 unquoted[ii] != '_' && 430 // If this is the part of a UTF8 or Latin1 character, we need 431 // to copy this byte without escaping. Experimentally this is 432 // what works correctly with the regexp library. 433 !(unquoted[ii] & 128)) { 434 if (unquoted[ii] == '\0') { // Special handling for null chars. 435 // Can't use "\\0" since the next character might be a digit. 436 result += "\\x00"; 437 continue; 438 } 439 result += '\\'; 440 } 441 result += unquoted[ii]; 442 } 443 444 return result; 445 } 446 447 /***** Actual matching and rewriting code *****/ 448 449 bool PCRE::HitLimit() { 450 return hit_limit_; 451 } 452 453 void PCRE::ClearHitLimit() { 454 hit_limit_ = 0; 455 } 456 457 int PCRE::TryMatch(const StringPiece& text, 458 int startpos, 459 Anchor anchor, 460 bool empty_ok, 461 int *vec, 462 int vecsize) const { 463 pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_; 464 if (re == NULL) { 465 PCREPORT(ERROR) << "Matching against invalid re: " << *error_; 466 return 0; 467 } 468 469 int match_limit = match_limit_; 470 if (match_limit <= 0) { 471 match_limit = FLAGS_regexp_match_limit; 472 } 473 474 int stack_limit = stack_limit_; 475 if (stack_limit <= 0) { 476 stack_limit = FLAGS_regexp_stack_limit; 477 } 478 479 pcre_extra extra = { 0 }; 480 if (match_limit > 0) { 481 extra.flags |= PCRE_EXTRA_MATCH_LIMIT; 482 extra.match_limit = match_limit; 483 } 484 if (stack_limit > 0) { 485 extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; 486 extra.match_limit_recursion = stack_limit / kPCREFrameSize; 487 } 488 489 int options = 0; 490 if (anchor != UNANCHORED) 491 options |= PCRE_ANCHORED; 492 if (!empty_ok) 493 options |= PCRE_NOTEMPTY; 494 495 int rc = pcre_exec(re, // The regular expression object 496 &extra, 497 (text.data() == NULL) ? "" : text.data(), 498 text.size(), 499 startpos, 500 options, 501 vec, 502 vecsize); 503 504 // Handle errors 505 if (rc == 0) { 506 // pcre_exec() returns 0 as a special case when the number of 507 // capturing subpatterns exceeds the size of the vector. 508 // When this happens, there is a match and the output vector 509 // is filled, but we miss out on the positions of the extra subpatterns. 510 rc = vecsize / 2; 511 } else if (rc < 0) { 512 switch (rc) { 513 case PCRE_ERROR_NOMATCH: 514 return 0; 515 case PCRE_ERROR_MATCHLIMIT: 516 // Writing to hit_limit is not safe if multiple threads 517 // are using the PCRE, but the flag is only intended 518 // for use by unit tests anyway, so we let it go. 519 hit_limit_ = true; 520 PCREPORT(WARNING) << "Exceeded match limit of " << match_limit 521 << " when matching '" << pattern_ << "'" 522 << " against text that is " << text.size() << " bytes."; 523 return 0; 524 case PCRE_ERROR_RECURSIONLIMIT: 525 // See comment about hit_limit above. 526 hit_limit_ = true; 527 PCREPORT(WARNING) << "Exceeded stack limit of " << stack_limit 528 << " when matching '" << pattern_ << "'" 529 << " against text that is " << text.size() << " bytes."; 530 return 0; 531 default: 532 // There are other return codes from pcre.h : 533 // PCRE_ERROR_NULL (-2) 534 // PCRE_ERROR_BADOPTION (-3) 535 // PCRE_ERROR_BADMAGIC (-4) 536 // PCRE_ERROR_UNKNOWN_NODE (-5) 537 // PCRE_ERROR_NOMEMORY (-6) 538 // PCRE_ERROR_NOSUBSTRING (-7) 539 // ... 540 PCREPORT(ERROR) << "Unexpected return code: " << rc 541 << " when matching '" << pattern_ << "'" 542 << ", re=" << re 543 << ", text=" << text 544 << ", vec=" << vec 545 << ", vecsize=" << vecsize; 546 return 0; 547 } 548 } 549 550 return rc; 551 } 552 553 bool PCRE::DoMatchImpl(const StringPiece& text, 554 Anchor anchor, 555 int* consumed, 556 const Arg* const* args, 557 int n, 558 int* vec, 559 int vecsize) const { 560 assert((1 + n) * 3 <= vecsize); // results + PCRE workspace 561 int matches = TryMatch(text, 0, anchor, true, vec, vecsize); 562 assert(matches >= 0); // TryMatch never returns negatives 563 if (matches == 0) 564 return false; 565 566 *consumed = vec[1]; 567 568 if (n == 0 || args == NULL) { 569 // We are not interested in results 570 return true; 571 } 572 if (NumberOfCapturingGroups() < n) { 573 // PCRE has fewer capturing groups than number of arg pointers passed in 574 return false; 575 } 576 577 // If we got here, we must have matched the whole pattern. 578 // We do not need (can not do) any more checks on the value of 'matches' here 579 // -- see the comment for TryMatch. 580 for (int i = 0; i < n; i++) { 581 const int start = vec[2*(i+1)]; 582 const int limit = vec[2*(i+1)+1]; 583 if (!args[i]->Parse(text.data() + start, limit-start)) { 584 // TODO: Should we indicate what the error was? 585 return false; 586 } 587 } 588 589 return true; 590 } 591 592 bool PCRE::DoMatch(const StringPiece& text, 593 Anchor anchor, 594 int* consumed, 595 const Arg* const args[], 596 int n) const { 597 assert(n >= 0); 598 size_t const vecsize = (1 + n) * 3; // results + PCRE workspace 599 // (as for kVecSize) 600 int *vec = new int[vecsize]; 601 bool b = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize); 602 delete[] vec; 603 return b; 604 } 605 606 bool PCRE::Rewrite(string *out, const StringPiece &rewrite, 607 const StringPiece &text, int *vec, int veclen) const { 608 int number_of_capturing_groups = NumberOfCapturingGroups(); 609 for (const char *s = rewrite.data(), *end = s + rewrite.size(); 610 s < end; s++) { 611 int c = *s; 612 if (c == '\\') { 613 c = *++s; 614 if (isdigit(c)) { 615 int n = (c - '0'); 616 if (n >= veclen) { 617 if (n <= number_of_capturing_groups) { 618 // unmatched optional capturing group. treat 619 // its value as empty string; i.e., nothing to append. 620 } else { 621 PCREPORT(ERROR) << "requested group " << n 622 << " in regexp " << rewrite.data(); 623 return false; 624 } 625 } 626 int start = vec[2 * n]; 627 if (start >= 0) 628 out->append(text.data() + start, vec[2 * n + 1] - start); 629 } else if (c == '\\') { 630 out->push_back('\\'); 631 } else { 632 PCREPORT(ERROR) << "invalid rewrite pattern: " << rewrite.data(); 633 return false; 634 } 635 } else { 636 out->push_back(c); 637 } 638 } 639 return true; 640 } 641 642 bool PCRE::CheckRewriteString(const StringPiece& rewrite, string* error) const { 643 int max_token = -1; 644 for (const char *s = rewrite.data(), *end = s + rewrite.size(); 645 s < end; s++) { 646 int c = *s; 647 if (c != '\\') { 648 continue; 649 } 650 if (++s == end) { 651 *error = "Rewrite schema error: '\\' not allowed at end."; 652 return false; 653 } 654 c = *s; 655 if (c == '\\') { 656 continue; 657 } 658 if (!isdigit(c)) { 659 *error = "Rewrite schema error: " 660 "'\\' must be followed by a digit or '\\'."; 661 return false; 662 } 663 int n = (c - '0'); 664 if (max_token < n) { 665 max_token = n; 666 } 667 } 668 669 if (max_token > NumberOfCapturingGroups()) { 670 SStringPrintf(error, "Rewrite schema requests %d matches, " 671 "but the regexp only has %d parenthesized subexpressions.", 672 max_token, NumberOfCapturingGroups()); 673 return false; 674 } 675 return true; 676 } 677 678 679 // Return the number of capturing subpatterns, or -1 if the 680 // regexp wasn't valid on construction. 681 int PCRE::NumberOfCapturingGroups() const { 682 if (re_partial_ == NULL) return -1; 683 684 int result; 685 CHECK(pcre_fullinfo(re_partial_, // The regular expression object 686 NULL, // We did not study the pattern 687 PCRE_INFO_CAPTURECOUNT, 688 &result) == 0); 689 return result; 690 } 691 692 693 /***** Parsers for various types *****/ 694 695 bool PCRE::Arg::parse_null(const char* str, int n, void* dest) { 696 // We fail if somebody asked us to store into a non-NULL void* pointer 697 return (dest == NULL); 698 } 699 700 bool PCRE::Arg::parse_string(const char* str, int n, void* dest) { 701 if (dest == NULL) return true; 702 reinterpret_cast<string*>(dest)->assign(str, n); 703 return true; 704 } 705 706 bool PCRE::Arg::parse_stringpiece(const char* str, int n, void* dest) { 707 if (dest == NULL) return true; 708 reinterpret_cast<StringPiece*>(dest)->set(str, n); 709 return true; 710 } 711 712 bool PCRE::Arg::parse_char(const char* str, int n, void* dest) { 713 if (n != 1) return false; 714 if (dest == NULL) return true; 715 *(reinterpret_cast<char*>(dest)) = str[0]; 716 return true; 717 } 718 719 bool PCRE::Arg::parse_uchar(const char* str, int n, void* dest) { 720 if (n != 1) return false; 721 if (dest == NULL) return true; 722 *(reinterpret_cast<unsigned char*>(dest)) = str[0]; 723 return true; 724 } 725 726 // Largest number spec that we are willing to parse 727 static const int kMaxNumberLength = 32; 728 729 // PCREQUIPCRES "buf" must have length at least kMaxNumberLength+1 730 // PCREQUIPCRES "n > 0" 731 // Copies "str" into "buf" and null-terminates if necessary. 732 // Returns one of: 733 // a. "str" if no termination is needed 734 // b. "buf" if the string was copied and null-terminated 735 // c. "" if the input was invalid and has no hope of being parsed 736 static const char* TerminateNumber(char* buf, const char* str, int n) { 737 if ((n > 0) && isspace(*str)) { 738 // We are less forgiving than the strtoxxx() routines and do not 739 // allow leading spaces. 740 return ""; 741 } 742 743 // See if the character right after the input text may potentially 744 // look like a digit. 745 if (isdigit(str[n]) || 746 ((str[n] >= 'a') && (str[n] <= 'f')) || 747 ((str[n] >= 'A') && (str[n] <= 'F'))) { 748 if (n > kMaxNumberLength) return ""; // Input too big to be a valid number 749 memcpy(buf, str, n); 750 buf[n] = '\0'; 751 return buf; 752 } else { 753 // We can parse right out of the supplied string, so return it. 754 return str; 755 } 756 } 757 758 bool PCRE::Arg::parse_long_radix(const char* str, 759 int n, 760 void* dest, 761 int radix) { 762 if (n == 0) return false; 763 char buf[kMaxNumberLength+1]; 764 str = TerminateNumber(buf, str, n); 765 char* end; 766 errno = 0; 767 long r = strtol(str, &end, radix); 768 if (end != str + n) return false; // Leftover junk 769 if (errno) return false; 770 if (dest == NULL) return true; 771 *(reinterpret_cast<long*>(dest)) = r; 772 return true; 773 } 774 775 bool PCRE::Arg::parse_ulong_radix(const char* str, 776 int n, 777 void* dest, 778 int radix) { 779 if (n == 0) return false; 780 char buf[kMaxNumberLength+1]; 781 str = TerminateNumber(buf, str, n); 782 if (str[0] == '-') { 783 // strtoul() will silently accept negative numbers and parse 784 // them. This module is more strict and treats them as errors. 785 return false; 786 } 787 788 char* end; 789 errno = 0; 790 unsigned long r = strtoul(str, &end, radix); 791 if (end != str + n) return false; // Leftover junk 792 if (errno) return false; 793 if (dest == NULL) return true; 794 *(reinterpret_cast<unsigned long*>(dest)) = r; 795 return true; 796 } 797 798 bool PCRE::Arg::parse_short_radix(const char* str, 799 int n, 800 void* dest, 801 int radix) { 802 long r; 803 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse 804 if ((short)r != r) return false; // Out of range 805 if (dest == NULL) return true; 806 *(reinterpret_cast<short*>(dest)) = r; 807 return true; 808 } 809 810 bool PCRE::Arg::parse_ushort_radix(const char* str, 811 int n, 812 void* dest, 813 int radix) { 814 unsigned long r; 815 if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse 816 if ((ushort)r != r) return false; // Out of range 817 if (dest == NULL) return true; 818 *(reinterpret_cast<unsigned short*>(dest)) = r; 819 return true; 820 } 821 822 bool PCRE::Arg::parse_int_radix(const char* str, 823 int n, 824 void* dest, 825 int radix) { 826 long r; 827 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse 828 if ((int)r != r) return false; // Out of range 829 if (dest == NULL) return true; 830 *(reinterpret_cast<int*>(dest)) = r; 831 return true; 832 } 833 834 bool PCRE::Arg::parse_uint_radix(const char* str, 835 int n, 836 void* dest, 837 int radix) { 838 unsigned long r; 839 if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse 840 if ((uint)r != r) return false; // Out of range 841 if (dest == NULL) return true; 842 *(reinterpret_cast<unsigned int*>(dest)) = r; 843 return true; 844 } 845 846 bool PCRE::Arg::parse_longlong_radix(const char* str, 847 int n, 848 void* dest, 849 int radix) { 850 if (n == 0) return false; 851 char buf[kMaxNumberLength+1]; 852 str = TerminateNumber(buf, str, n); 853 char* end; 854 errno = 0; 855 int64 r = strtoll(str, &end, radix); 856 if (end != str + n) return false; // Leftover junk 857 if (errno) return false; 858 if (dest == NULL) return true; 859 *(reinterpret_cast<int64*>(dest)) = r; 860 return true; 861 } 862 863 bool PCRE::Arg::parse_ulonglong_radix(const char* str, 864 int n, 865 void* dest, 866 int radix) { 867 if (n == 0) return false; 868 char buf[kMaxNumberLength+1]; 869 str = TerminateNumber(buf, str, n); 870 if (str[0] == '-') { 871 // strtoull() will silently accept negative numbers and parse 872 // them. This module is more strict and treats them as errors. 873 return false; 874 } 875 char* end; 876 errno = 0; 877 uint64 r = strtoull(str, &end, radix); 878 if (end != str + n) return false; // Leftover junk 879 if (errno) return false; 880 if (dest == NULL) return true; 881 *(reinterpret_cast<uint64*>(dest)) = r; 882 return true; 883 } 884 885 bool PCRE::Arg::parse_double(const char* str, int n, void* dest) { 886 if (n == 0) return false; 887 static const int kMaxLength = 200; 888 char buf[kMaxLength]; 889 if (n >= kMaxLength) return false; 890 memcpy(buf, str, n); 891 buf[n] = '\0'; 892 errno = 0; 893 char* end; 894 double r = strtod(buf, &end); 895 if (end != buf + n) { 896 #ifdef COMPILER_MSVC 897 // Microsoft's strtod() doesn't handle inf and nan, so we have to 898 // handle it explicitly. Speed is not important here because this 899 // code is only called in unit tests. 900 bool pos = true; 901 const char* i = buf; 902 if ('-' == *i) { 903 pos = false; 904 ++i; 905 } else if ('+' == *i) { 906 ++i; 907 } 908 if (0 == stricmp(i, "inf") || 0 == stricmp(i, "infinity")) { 909 r = numeric_limits<double>::infinity(); 910 if (!pos) 911 r = -r; 912 } else if (0 == stricmp(i, "nan")) { 913 r = numeric_limits<double>::quiet_NaN(); 914 } else { 915 return false; 916 } 917 #else 918 return false; // Leftover junk 919 #endif 920 } 921 if (errno) return false; 922 if (dest == NULL) return true; 923 *(reinterpret_cast<double*>(dest)) = r; 924 return true; 925 } 926 927 bool PCRE::Arg::parse_float(const char* str, int n, void* dest) { 928 double r; 929 if (!parse_double(str, n, &r)) return false; 930 if (dest == NULL) return true; 931 *(reinterpret_cast<float*>(dest)) = static_cast<float>(r); 932 return true; 933 } 934 935 936 #define DEFINE_INTEGER_PARSERS(name) \ 937 bool PCRE::Arg::parse_##name(const char* str, int n, void* dest) { \ 938 return parse_##name##_radix(str, n, dest, 10); \ 939 } \ 940 bool PCRE::Arg::parse_##name##_hex(const char* str, int n, void* dest) { \ 941 return parse_##name##_radix(str, n, dest, 16); \ 942 } \ 943 bool PCRE::Arg::parse_##name##_octal(const char* str, int n, void* dest) { \ 944 return parse_##name##_radix(str, n, dest, 8); \ 945 } \ 946 bool PCRE::Arg::parse_##name##_cradix(const char* str, int n, void* dest) { \ 947 return parse_##name##_radix(str, n, dest, 0); \ 948 } 949 950 DEFINE_INTEGER_PARSERS(short); 951 DEFINE_INTEGER_PARSERS(ushort); 952 DEFINE_INTEGER_PARSERS(int); 953 DEFINE_INTEGER_PARSERS(uint); 954 DEFINE_INTEGER_PARSERS(long); 955 DEFINE_INTEGER_PARSERS(ulong); 956 DEFINE_INTEGER_PARSERS(longlong); 957 DEFINE_INTEGER_PARSERS(ulonglong); 958 959 #undef DEFINE_INTEGER_PARSERS 960 961 } // namespace re2 962