Menu

False positive: containerOutOfBounds flags container accesses gated by a same-named constant from a different namespace

Long Huang
2026-08-04
2026-08-04
  • Long Huang

    Long Huang - 2026-08-04

    containerOutOfBounds flags container accesses gated by a same-named constant from a different namespace, pulled in via using namespace

    Minimal reproduction:

    #include <QStringList>
    
    namespace TetheringState
    {
       constexpr int NUMBER_OF_RESPONSE_FIELDS = 2;
    }
    
    namespace TetheringStateV2
    {
       constexpr int NUMBER_OF_RESPONSE_FIELDS = 5;
    }
    
    void Parse(const QStringList& message)
    {
       using namespace TetheringStateV2;
       if(NUMBER_OF_RESPONSE_FIELDS == message.count())
       {
          auto a = message.at(0);
          auto b = message.at(1);
          auto c = message.at(2);
          auto d = message.at(3);
          auto e = message.at(4);
       }
    }
    

    TetheringState and TetheringStateV2 each declare a NUMBER_OF_RESPONSE_FIELDS constant. Inside Parse, using namespace TetheringStateV2 brings the value 5 into scope, so the guarded block only runs when message.count() == 5, making at(0)..at(4) all in bounds. cppcheck instead resolves NUMBER_OF_RESPONSE_FIELDS to the unrelated TetheringState::NUMBER_OF_RESPONSE_FIELDS (value 2), so it treats the guard as 2 == message.count() and flags every access past index 1 as out of bounds.

     
  • Aaron Danen

    Aaron Danen - 2026-08-04

    What version of cppcheck did you use to create this bug? I tried to reproduce this using the current master branch and this issue you describe didn't happen, even with --library=qt

    with --debug it looks like its working properly now:

    using the first namespace

    Checking examples/namespace.cpp ...
    
    ##file examples/namespace.cpp
    3: namespace TetheringState
    4: {
    5: constexpr int NUMBER_OF_RESPONSE_FIELDS@var1 = 2 ;
    6: }
    7:
    8: namespace TetheringStateV2
    9: {
    10: constexpr int NUMBER_OF_RESPONSE_FIELDS@var2 = 5 ;
    11: }
    12:
    13: void Parse ( const QStringList & message@var3 )
    14: {
    15: using namespace TetheringState ;
    16: if ( NUMBER_OF_RESPONSE_FIELDS@var1 ==@exprUNIQUE message@var3 .@exprUNIQUE count (@exprUNIQUE ) )
    17: {
    18: auto a@var4 ; a@var4 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 0 ) ;
    19: auto b@var5 ; b@var5 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 1 ) ;
    20: auto c@var6 ; c@var6 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 2 ) ;
    21: auto d@var7 ; d@var7 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 3 ) ;
    22: auto e@var8 ; e@var8 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 4 ) ;
    23: }
    24: }
    
    
    
    ##Value flow
    File examples/namespace.cpp
    Line 5
      NUMBER_OF_RESPONSE_FIELDS always 2
      = always 2
      2 always 2
    Line 10
      NUMBER_OF_RESPONSE_FIELDS always 5
      = always 5
      5 always 5
    Line 16
      NUMBER_OF_RESPONSE_FIELDS always 2 // correct!
      == always {!<=-1,!>=2}
    Line 18
      0 always 0
    Line 19
      1 always 1
    Line 20
      2 always 2
    Line 21
      3 always 3
    Line 22
      4 always 4
    

    and using the second namespace

    Checking examples/namespace.cpp ...
    
    
    ##file examples/namespace.cpp
    3: namespace TetheringState
    4: {
    5: constexpr int NUMBER_OF_RESPONSE_FIELDS@var1 = 2 ;
    6: }
    7:
    8: namespace TetheringStateV2
    9: {
    10: constexpr int NUMBER_OF_RESPONSE_FIELDS@var2 = 5 ;
    11: }
    12:
    13: void Parse ( const QStringList & message@var3 )
    14: {
    15: using namespace TetheringStateV2 ;
    16: if ( NUMBER_OF_RESPONSE_FIELDS@var2 ==@exprUNIQUE message@var3 .@exprUNIQUE count (@exprUNIQUE ) )
    17: {
    18: auto a@var4 ; a@var4 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 0 ) ;
    19: auto b@var5 ; b@var5 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 1 ) ;
    20: auto c@var6 ; c@var6 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 2 ) ;
    21: auto d@var7 ; d@var7 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 3 ) ;
    22: auto e@var8 ; e@var8 =@exprUNIQUE message@var3 .@expr14 at (@exprUNIQUE 4 ) ;
    23: }
    24: }
    
    
    
    ##Value flow
    File examples/namespace.cpp
    Line 5
      NUMBER_OF_RESPONSE_FIELDS always 2
      = always 2
      2 always 2
    Line 10
      NUMBER_OF_RESPONSE_FIELDS always 5
      = always 5
      5 always 5
    Line 16
      NUMBER_OF_RESPONSE_FIELDS always 5 // correct!
      == always {!<=-1,!>=2}
    Line 18
      0 always 0
    Line 19
      1 always 1
    Line 20
      2 always 2
    Line 21
      3 always 3
    Line 22
      4 always 4
    

    it might be related to#14859, and #14948

     

Log in to post a comment.