43
43
#include " valueflow.h"
44
44
#include " version.h"
45
45
46
+ #ifdef HAVE_RULES
47
+ #include " regex.h"
48
+ #endif
49
+
46
50
#include < algorithm>
47
51
#include < cassert>
48
52
#include < cstdio>
65
69
#include < vector>
66
70
67
71
#include " json.h"
68
-
69
- #include < simplecpp.h>
70
-
71
72
#include " xml.h"
72
73
73
- #ifdef HAVE_RULES
74
- #ifdef _WIN32
75
- #define PCRE_STATIC
76
- #endif
77
- #include < pcre.h>
78
- #endif
74
+ #include < simplecpp.h>
79
75
80
76
class SymbolDatabase ;
81
77
@@ -1401,135 +1397,6 @@ bool CppCheck::hasRule(const std::string &tokenlist) const
1401
1397
});
1402
1398
}
1403
1399
1404
- static const char * pcreErrorCodeToString (const int pcreExecRet)
1405
- {
1406
- switch (pcreExecRet) {
1407
- case PCRE_ERROR_NULL:
1408
- return " Either code or subject was passed as NULL, or ovector was NULL "
1409
- " and ovecsize was not zero (PCRE_ERROR_NULL)" ;
1410
- case PCRE_ERROR_BADOPTION:
1411
- return " An unrecognized bit was set in the options argument (PCRE_ERROR_BADOPTION)" ;
1412
- case PCRE_ERROR_BADMAGIC:
1413
- return " PCRE stores a 4-byte \" magic number\" at the start of the compiled code, "
1414
- " to catch the case when it is passed a junk pointer and to detect when a "
1415
- " pattern that was compiled in an environment of one endianness is run in "
1416
- " an environment with the other endianness. This is the error that PCRE "
1417
- " gives when the magic number is not present (PCRE_ERROR_BADMAGIC)" ;
1418
- case PCRE_ERROR_UNKNOWN_NODE:
1419
- return " While running the pattern match, an unknown item was encountered in the "
1420
- " compiled pattern. This error could be caused by a bug in PCRE or by "
1421
- " overwriting of the compiled pattern (PCRE_ERROR_UNKNOWN_NODE)" ;
1422
- case PCRE_ERROR_NOMEMORY:
1423
- return " If a pattern contains back references, but the ovector that is passed "
1424
- " to pcre_exec() is not big enough to remember the referenced substrings, "
1425
- " PCRE gets a block of memory at the start of matching to use for this purpose. "
1426
- " If the call via pcre_malloc() fails, this error is given. The memory is "
1427
- " automatically freed at the end of matching. This error is also given if "
1428
- " pcre_stack_malloc() fails in pcre_exec(). "
1429
- " This can happen only when PCRE has been compiled with "
1430
- " --disable-stack-for-recursion (PCRE_ERROR_NOMEMORY)" ;
1431
- case PCRE_ERROR_NOSUBSTRING:
1432
- return " This error is used by the pcre_copy_substring(), pcre_get_substring(), "
1433
- " and pcre_get_substring_list() functions (see below). "
1434
- " It is never returned by pcre_exec() (PCRE_ERROR_NOSUBSTRING)" ;
1435
- case PCRE_ERROR_MATCHLIMIT:
1436
- return " The backtracking limit, as specified by the match_limit field in a pcre_extra "
1437
- " structure (or defaulted) was reached. "
1438
- " See the description above (PCRE_ERROR_MATCHLIMIT)" ;
1439
- case PCRE_ERROR_CALLOUT:
1440
- return " This error is never generated by pcre_exec() itself. "
1441
- " It is provided for use by callout functions that want to yield a distinctive "
1442
- " error code. See the pcrecallout documentation for details (PCRE_ERROR_CALLOUT)" ;
1443
- case PCRE_ERROR_BADUTF8:
1444
- return " A string that contains an invalid UTF-8 byte sequence was passed as a subject, "
1445
- " and the PCRE_NO_UTF8_CHECK option was not set. If the size of the output vector "
1446
- " (ovecsize) is at least 2, the byte offset to the start of the the invalid UTF-8 "
1447
- " character is placed in the first element, and a reason code is placed in the "
1448
- " second element. The reason codes are listed in the following section. For "
1449
- " backward compatibility, if PCRE_PARTIAL_HARD is set and the problem is a truncated "
1450
- " UTF-8 character at the end of the subject (reason codes 1 to 5), "
1451
- " PCRE_ERROR_SHORTUTF8 is returned instead of PCRE_ERROR_BADUTF8" ;
1452
- case PCRE_ERROR_BADUTF8_OFFSET:
1453
- return " The UTF-8 byte sequence that was passed as a subject was checked and found to "
1454
- " be valid (the PCRE_NO_UTF8_CHECK option was not set), but the value of "
1455
- " startoffset did not point to the beginning of a UTF-8 character or the end of "
1456
- " the subject (PCRE_ERROR_BADUTF8_OFFSET)" ;
1457
- case PCRE_ERROR_PARTIAL:
1458
- return " The subject string did not match, but it did match partially. See the "
1459
- " pcrepartial documentation for details of partial matching (PCRE_ERROR_PARTIAL)" ;
1460
- case PCRE_ERROR_BADPARTIAL:
1461
- return " This code is no longer in use. It was formerly returned when the PCRE_PARTIAL "
1462
- " option was used with a compiled pattern containing items that were not supported "
1463
- " for partial matching. From release 8.00 onwards, there are no restrictions on "
1464
- " partial matching (PCRE_ERROR_BADPARTIAL)" ;
1465
- case PCRE_ERROR_INTERNAL:
1466
- return " An unexpected internal error has occurred. This error could be caused by a bug "
1467
- " in PCRE or by overwriting of the compiled pattern (PCRE_ERROR_INTERNAL)" ;
1468
- case PCRE_ERROR_BADCOUNT:
1469
- return " This error is given if the value of the ovecsize argument is negative "
1470
- " (PCRE_ERROR_BADCOUNT)" ;
1471
- case PCRE_ERROR_RECURSIONLIMIT:
1472
- return " The internal recursion limit, as specified by the match_limit_recursion "
1473
- " field in a pcre_extra structure (or defaulted) was reached. "
1474
- " See the description above (PCRE_ERROR_RECURSIONLIMIT)" ;
1475
- case PCRE_ERROR_DFA_UITEM:
1476
- return " PCRE_ERROR_DFA_UITEM" ;
1477
- case PCRE_ERROR_DFA_UCOND:
1478
- return " PCRE_ERROR_DFA_UCOND" ;
1479
- case PCRE_ERROR_DFA_WSSIZE:
1480
- return " PCRE_ERROR_DFA_WSSIZE" ;
1481
- case PCRE_ERROR_DFA_RECURSE:
1482
- return " PCRE_ERROR_DFA_RECURSE" ;
1483
- case PCRE_ERROR_NULLWSLIMIT:
1484
- return " PCRE_ERROR_NULLWSLIMIT" ;
1485
- case PCRE_ERROR_BADNEWLINE:
1486
- return " An invalid combination of PCRE_NEWLINE_xxx options was "
1487
- " given (PCRE_ERROR_BADNEWLINE)" ;
1488
- case PCRE_ERROR_BADOFFSET:
1489
- return " The value of startoffset was negative or greater than the length "
1490
- " of the subject, that is, the value in length (PCRE_ERROR_BADOFFSET)" ;
1491
- case PCRE_ERROR_SHORTUTF8:
1492
- return " This error is returned instead of PCRE_ERROR_BADUTF8 when the subject "
1493
- " string ends with a truncated UTF-8 character and the PCRE_PARTIAL_HARD option is set. "
1494
- " Information about the failure is returned as for PCRE_ERROR_BADUTF8. "
1495
- " It is in fact sufficient to detect this case, but this special error code for "
1496
- " PCRE_PARTIAL_HARD precedes the implementation of returned information; "
1497
- " it is retained for backwards compatibility (PCRE_ERROR_SHORTUTF8)" ;
1498
- case PCRE_ERROR_RECURSELOOP:
1499
- return " This error is returned when pcre_exec() detects a recursion loop "
1500
- " within the pattern. Specifically, it means that either the whole pattern "
1501
- " or a subpattern has been called recursively for the second time at the same "
1502
- " position in the subject string. Some simple patterns that might do this "
1503
- " are detected and faulted at compile time, but more complicated cases, "
1504
- " in particular mutual recursions between two different subpatterns, "
1505
- " cannot be detected until run time (PCRE_ERROR_RECURSELOOP)" ;
1506
- case PCRE_ERROR_JIT_STACKLIMIT:
1507
- return " This error is returned when a pattern that was successfully studied "
1508
- " using a JIT compile option is being matched, but the memory available "
1509
- " for the just-in-time processing stack is not large enough. See the pcrejit "
1510
- " documentation for more details (PCRE_ERROR_JIT_STACKLIMIT)" ;
1511
- case PCRE_ERROR_BADMODE:
1512
- return " This error is given if a pattern that was compiled by the 8-bit library "
1513
- " is passed to a 16-bit or 32-bit library function, or vice versa (PCRE_ERROR_BADMODE)" ;
1514
- case PCRE_ERROR_BADENDIANNESS:
1515
- return " This error is given if a pattern that was compiled and saved is reloaded on a "
1516
- " host with different endianness. The utility function pcre_pattern_to_host_byte_order() "
1517
- " can be used to convert such a pattern so that it runs on the new host (PCRE_ERROR_BADENDIANNESS)" ;
1518
- case PCRE_ERROR_DFA_BADRESTART:
1519
- return " PCRE_ERROR_DFA_BADRESTART" ;
1520
- #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
1521
- case PCRE_ERROR_BADLENGTH:
1522
- return " This error is given if pcre_exec() is called with a negative value for the length argument (PCRE_ERROR_BADLENGTH)" ;
1523
- case PCRE_ERROR_JIT_BADOPTION:
1524
- return " This error is returned when a pattern that was successfully studied using a JIT compile "
1525
- " option is being matched, but the matching mode (partial or complete match) does not correspond "
1526
- " to any JIT compilation mode. When the JIT fast path function is used, this error may be "
1527
- " also given for invalid options. See the pcrejit documentation for more details (PCRE_ERROR_JIT_BADOPTION)" ;
1528
- #endif
1529
- }
1530
- return " " ;
1531
- }
1532
-
1533
1400
void CppCheck::executeRules (const std::string &tokenlist, const TokenList &list)
1534
1401
{
1535
1402
// There is no rule to execute
@@ -1551,73 +1418,7 @@ void CppCheck::executeRules(const std::string &tokenlist, const TokenList &list)
1551
1418
mErrorLogger .reportOut (" Processing rule: " + rule.pattern , Color::FgGreen);
1552
1419
}
1553
1420
1554
- const char *pcreCompileErrorStr = nullptr ;
1555
- int erroffset = 0 ;
1556
- pcre * const re = pcre_compile (rule.pattern .c_str (),0 ,&pcreCompileErrorStr,&erroffset,nullptr );
1557
- if (!re) {
1558
- if (pcreCompileErrorStr) {
1559
- const std::string msg = " pcre_compile failed: " + std::string (pcreCompileErrorStr);
1560
- const ErrorMessage errmsg (std::list<ErrorMessage::FileLocation>(),
1561
- " " ,
1562
- Severity::error,
1563
- msg,
1564
- " pcre_compile" ,
1565
- Certainty::normal);
1566
-
1567
- mErrorLogger .reportErr (errmsg);
1568
- }
1569
- continue ;
1570
- }
1571
-
1572
- // Optimize the regex, but only if PCRE_CONFIG_JIT is available
1573
- #ifdef PCRE_CONFIG_JIT
1574
- const char *pcreStudyErrorStr = nullptr ;
1575
- pcre_extra * const pcreExtra = pcre_study (re, PCRE_STUDY_JIT_COMPILE, &pcreStudyErrorStr);
1576
- // pcre_study() returns NULL for both errors and when it can not optimize the regex.
1577
- // The last argument is how one checks for errors.
1578
- // It is NULL if everything works, and points to an error string otherwise.
1579
- if (pcreStudyErrorStr) {
1580
- const std::string msg = " pcre_study failed: " + std::string (pcreStudyErrorStr);
1581
- const ErrorMessage errmsg (std::list<ErrorMessage::FileLocation>(),
1582
- " " ,
1583
- Severity::error,
1584
- msg,
1585
- " pcre_study" ,
1586
- Certainty::normal);
1587
-
1588
- mErrorLogger .reportErr (errmsg);
1589
- // pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile().
1590
- pcre_free (re);
1591
- continue ;
1592
- }
1593
- #else
1594
- const pcre_extra * const pcreExtra = nullptr ;
1595
- #endif
1596
-
1597
- int pos = 0 ;
1598
- int ovector[30 ]= {0 };
1599
- while (pos < (int )str.size ()) {
1600
- const int pcreExecRet = pcre_exec (re, pcreExtra, str.c_str (), (int )str.size (), pos, 0 , ovector, 30 );
1601
- if (pcreExecRet < 0 ) {
1602
- const std::string errorMessage = pcreErrorCodeToString (pcreExecRet);
1603
- if (!errorMessage.empty ()) {
1604
- const ErrorMessage errmsg (std::list<ErrorMessage::FileLocation>(),
1605
- " " ,
1606
- Severity::error,
1607
- std::string (" pcre_exec failed: " ) + errorMessage,
1608
- " pcre_exec" ,
1609
- Certainty::normal);
1610
-
1611
- mErrorLogger .reportErr (errmsg);
1612
- }
1613
- break ;
1614
- }
1615
- const auto pos1 = (unsigned int )ovector[0 ];
1616
- const auto pos2 = (unsigned int )ovector[1 ];
1617
-
1618
- // jump to the end of the match for the next pcre_exec
1619
- pos = (int )pos2;
1620
-
1421
+ auto f = [&](int pos1, int pos2) {
1621
1422
// determine location..
1622
1423
int fileIndex = 0 ;
1623
1424
int line = 0 ;
@@ -1646,15 +1447,19 @@ void CppCheck::executeRules(const std::string &tokenlist, const TokenList &list)
1646
1447
1647
1448
// Report error
1648
1449
mErrorLogger .reportErr (errmsg);
1649
- }
1450
+ };
1451
+
1452
+ const std::string err = rule.regex .match (str, f);
1453
+ if (!err.empty ()) {
1454
+ const ErrorMessage errmsg (std::list<ErrorMessage::FileLocation>(),
1455
+ emptyString,
1456
+ Severity::error,
1457
+ err,
1458
+ " pcre_exec" ,
1459
+ Certainty::normal);
1650
1460
1651
- pcre_free (re);
1652
- #ifdef PCRE_CONFIG_JIT
1653
- // Free up the EXTRA PCRE value (may be NULL at this point)
1654
- if (pcreExtra) {
1655
- pcre_free_study (pcreExtra);
1461
+ mErrorLogger .reportErr (errmsg);
1656
1462
}
1657
- #endif
1658
1463
}
1659
1464
}
1660
1465
#endif
0 commit comments