@@ -621,80 +621,85 @@ int main() {
621621 const picojson::object& driver = tool.at (" driver" ).get <picojson::object>();
622622 const picojson::array& rules = driver.at (" rules" ).get <picojson::array>();
623623
624- // Check that security-related rules have CWE tags
624+ // Check that rules with CWE IDs have CWE tags (regardless of security classification)
625625 bool foundNullPointerWithCwe = false ;
626626 bool foundArrayBoundsWithCwe = false ;
627627 bool foundMemleakWithCwe = false ;
628628 bool foundDoubleFreeWithCwe = false ;
629+ bool foundAnyCweTag = false ;
629630
630631 for (const auto & rule : rules)
631632 {
632- const picojson::object& r = rule.get <picojson::object>();
633- const std::string ruleId = r.at (" id" ).get <std::string>();
633+ const picojson::object& r = rule.get <picojson::object>();
634+ const std::string ruleId = r.at (" id" ).get <std::string>();
635+ const picojson::object& props = r.at (" properties" ).get <picojson::object>();
634636
635- // Only check security-related rules that should have CWE tags
636- if (ruleId == " nullPointer" || ruleId == " arrayIndexOutOfBounds" || ruleId == " doubleFree" ||
637- ruleId == " memleak" )
637+ // Check if this rule has tags
638+ if (props.find (" tags" ) != props.end ())
638639 {
639- const picojson::object& props = r .at (" properties " ).get <picojson::object >();
640+ const picojson::array& tags = props .at (" tags " ).get <picojson::array >();
640641
641- // Verify this rule has security-severity (prerequisite for CWE tags)
642- if (props.find (" security-severity" ) != props.end ())
642+ bool hasSecurityTag = false ;
643+ bool hasCweTag = false ;
644+ std::string cweTag;
645+
646+ for (const auto & tag : tags)
643647 {
644- // Should have tags array
645- ASSERT (props.find (" tags" ) != props.end ());
646- const picojson::array& tags = props.at (" tags" ).get <picojson::array>();
648+ const std::string tagStr = tag.get <std::string>();
649+ if (tagStr == " security" )
650+ {
651+ hasSecurityTag = true ;
652+ }
653+ else if (tagStr.find (" external/cwe/cwe-" ) == 0 )
654+ {
655+ hasCweTag = true ;
656+ foundAnyCweTag = true ;
657+ cweTag = tagStr;
647658
648- bool hasSecurityTag = false ;
649- bool hasCweTag = false ;
650- std::string cweTag;
659+ // Validate CWE tag format: external/cwe/cwe-<number>
660+ ASSERT_EQUALS (0 , tagStr.find (" external/cwe/cwe-" ));
661+ std::string cweNumber = tagStr.substr (17 ); // After "external/cwe/cwe-"
662+ ASSERT (cweNumber.length () > 0 );
651663
652- for (const auto & tag : tags)
653- {
654- const std::string tagStr = tag.get <std::string>();
655- if (tagStr == " security" )
664+ // Verify it's a valid number
665+ for (char c : cweNumber)
656666 {
657- hasSecurityTag = true ;
667+ ASSERT (c >= ' 0 ' && c <= ' 9 ' ) ;
658668 }
659- else if (tagStr.find (" external/cwe/cwe-" ) == 0 )
660- {
661- hasCweTag = true ;
662- cweTag = tagStr;
663-
664- // Validate CWE tag format: external/cwe/cwe-<number>
665- ASSERT_EQUALS (0 , tagStr.find (" external/cwe/cwe-" ));
666- std::string cweNumber = tagStr.substr (17 ); // After "external/cwe/cwe-"
667- ASSERT (cweNumber.length () > 0 );
668-
669- // Verify it's a valid number
670- for (char c : cweNumber)
671- {
672- ASSERT (c >= ' 0' && c <= ' 9' );
673- }
674669
675- // Track specific CWE mappings we expect
676- if (ruleId == " nullPointer" && cweNumber == " 476" )
677- foundNullPointerWithCwe = true ;
678- else if (ruleId == " arrayIndexOutOfBounds" && cweNumber == " 788" )
679- foundArrayBoundsWithCwe = true ;
680- else if (ruleId == " memleak" && cweNumber == " 401" )
681- foundMemleakWithCwe = true ;
682- else if (ruleId == " doubleFree" && cweNumber == " 415" )
683- foundDoubleFreeWithCwe = true ;
684- }
670+ // Track specific CWE mappings we expect for security-related rules
671+ if (ruleId == " nullPointer" && cweNumber == " 476" )
672+ foundNullPointerWithCwe = true ;
673+ else if (ruleId == " arrayIndexOutOfBounds" && cweNumber == " 788" )
674+ foundArrayBoundsWithCwe = true ;
675+ else if (ruleId == " memleak" && cweNumber == " 401" )
676+ foundMemleakWithCwe = true ;
677+ else if (ruleId == " doubleFree" && cweNumber == " 415" )
678+ foundDoubleFreeWithCwe = true ;
685679 }
680+ }
686681
687- ASSERT_EQUALS (true , hasSecurityTag);
688- ASSERT_EQUALS (true , hasCweTag);
682+ // If this is a security-related rule with CWE, it should have both security and CWE tags
683+ if (hasCweTag && (ruleId == " nullPointer" || ruleId == " arrayIndexOutOfBounds" ||
684+ ruleId == " doubleFree" || ruleId == " memleak" ))
685+ {
686+ // Security-related rules should have security tag when they have security-severity
687+ if (props.find (" security-severity" ) != props.end ())
688+ {
689+ ASSERT_EQUALS (true , hasSecurityTag);
690+ }
689691 }
690692 }
691693 }
692694
693- // Verify we found at least some of the expected CWE mappings
695+ // Verify we found at least some CWE tags (from any rules, not just security-related)
696+ ASSERT_EQUALS (true , foundAnyCweTag);
697+
698+ // Verify we found at least some of the expected security-related CWE mappings
694699 // Note: Not all may be present depending on what the test code triggers
695- bool foundAnyCweMapping =
700+ bool foundSecurityCweMapping =
696701 foundNullPointerWithCwe || foundArrayBoundsWithCwe || foundMemleakWithCwe || foundDoubleFreeWithCwe;
697- ASSERT_EQUALS (true , foundAnyCweMapping );
702+ ASSERT_EQUALS (true , foundSecurityCweMapping );
698703 }
699704
700705 void sarifRuleCoverage ()
@@ -844,15 +849,18 @@ int main() {
844849 // Non-security rules should NOT have security-severity
845850 ASSERT (props.find (" security-severity" ) == props.end ());
846851
847- // If they have tags, they should not include security or CWE tags
852+ // If they have tags, they should not include the security tag
853+ // but they MAY include CWE tags if they have CWE mappings
848854 if (props.find (" tags" ) != props.end ())
849855 {
850856 const picojson::array& tags = props.at (" tags" ).get <picojson::array>();
851857 for (const auto & tag : tags)
852858 {
853859 const std::string tagStr = tag.get <std::string>();
860+ // Non-security rules should not have the security tag
854861 ASSERT (tagStr != " security" );
855- ASSERT (tagStr.find (" external/cwe/cwe-" ) != 0 );
862+ // But they may have CWE tags if they have CWE mappings
863+ // (no assertion against CWE tags here)
856864 }
857865 }
858866
0 commit comments