diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 167 | 
1 files changed, 90 insertions, 77 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index c3736d7e5d716..0693bd6fd94df 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -35,11 +35,8 @@ class CStringChecker : public Checker< eval::Call,                                           check::DeadSymbols,                                           check::RegionChanges                                           > { -  mutable OwningPtr<BugType> BT_Null, -                             BT_Bounds, -                             BT_Overlap, -                             BT_NotCString, -                             BT_AdditionOverflow; +  mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap, +      BT_NotCString, BT_AdditionOverflow;    mutable const char *CurrentFunctionDescription; @@ -51,6 +48,11 @@ public:      DefaultBool CheckCStringOutOfBounds;      DefaultBool CheckCStringBufferOverlap;      DefaultBool CheckCStringNotNullTerm; + +    CheckName CheckNameCStringNullArg; +    CheckName CheckNameCStringOutOfBounds; +    CheckName CheckNameCStringBufferOverlap; +    CheckName CheckNameCStringNotNullTerm;    };    CStringChecksFilter Filter; @@ -157,24 +159,24 @@ public:                                      ProgramStateRef state,                                      const Expr *S,                                      SVal l, -                                    const char *message = NULL) const; +                                    const char *message = nullptr) const;    ProgramStateRef CheckBufferAccess(CheckerContext &C,                                          ProgramStateRef state,                                          const Expr *Size,                                          const Expr *FirstBuf,                                          const Expr *SecondBuf, -                                        const char *firstMessage = NULL, -                                        const char *secondMessage = NULL, +                                        const char *firstMessage = nullptr, +                                        const char *secondMessage = nullptr,                                          bool WarnAboutSize = false) const;    ProgramStateRef CheckBufferAccess(CheckerContext &C,                                          ProgramStateRef state,                                          const Expr *Size,                                          const Expr *Buf, -                                        const char *message = NULL, +                                        const char *message = nullptr,                                          bool WarnAboutSize = false) const {      // This is a convenience override. -    return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL, +    return CheckBufferAccess(C, state, Size, Buf, nullptr, message, nullptr,                               WarnAboutSize);    }    ProgramStateRef CheckOverlap(CheckerContext &C, @@ -218,22 +220,23 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,                                              const Expr *S, SVal l) const {    // If a previous check has failed, propagate the failure.    if (!state) -    return NULL; +    return nullptr;    ProgramStateRef stateNull, stateNonNull; -  llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); +  std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());    if (stateNull && !stateNonNull) {      if (!Filter.CheckCStringNullArg) -      return NULL; +      return nullptr;      ExplodedNode *N = C.generateSink(stateNull);      if (!N) -      return NULL; +      return nullptr;      if (!BT_Null) -      BT_Null.reset(new BuiltinBug(categories::UnixAPI, -        "Null pointer argument in call to byte string function")); +      BT_Null.reset(new BuiltinBug( +          Filter.CheckNameCStringNullArg, categories::UnixAPI, +          "Null pointer argument in call to byte string function"));      SmallString<80> buf;      llvm::raw_svector_ostream os(buf); @@ -247,7 +250,7 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,      report->addRange(S->getSourceRange());      bugreporter::trackNullOrUndefValue(N, S, *report);      C.emitReport(report); -    return NULL; +    return nullptr;    }    // From here on, assume that the value is non-null. @@ -262,7 +265,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,                                               const char *warningMsg) const {    // If a previous check has failed, propagate the failure.    if (!state) -    return NULL; +    return nullptr;    // Check for out of bound array element access.    const MemRegion *R = l.getAsRegion(); @@ -291,11 +294,12 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,    if (StOutBound && !StInBound) {      ExplodedNode *N = C.generateSink(StOutBound);      if (!N) -      return NULL; +      return nullptr;      if (!BT_Bounds) { -      BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", -        "Byte string function accesses out-of-bound array element")); +      BT_Bounds.reset(new BuiltinBug( +          Filter.CheckNameCStringOutOfBounds, "Out-of-bound array access", +          "Byte string function accesses out-of-bound array element"));      }      BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get()); @@ -321,7 +325,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,      report->addRange(S->getSourceRange());      C.emitReport(report); -    return NULL; +    return nullptr;    }    // Array bound check succeeded.  From this point forward the array bound @@ -339,7 +343,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,                                                   bool WarnAboutSize) const {    // If a previous check has failed, propagate the failure.    if (!state) -    return NULL; +    return nullptr;    SValBuilder &svalBuilder = C.getSValBuilder();    ASTContext &Ctx = svalBuilder.getContext(); @@ -352,7 +356,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,    SVal BufVal = state->getSVal(FirstBuf, LCtx);    state = checkNonNull(C, state, FirstBuf, BufVal);    if (!state) -    return NULL; +    return nullptr;    // If out-of-bounds checking is turned off, skip the rest.    if (!Filter.CheckCStringOutOfBounds) @@ -382,7 +386,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,      // If the buffer isn't large enough, abort.      if (!state) -      return NULL; +      return nullptr;    }    // If there's a second buffer, check it as well. @@ -390,7 +394,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,      BufVal = state->getSVal(SecondBuf, LCtx);      state = checkNonNull(C, state, SecondBuf, BufVal);      if (!state) -      return NULL; +      return nullptr;      BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());      if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) { @@ -420,7 +424,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,    // If a previous check has failed, propagate the failure.    if (!state) -    return NULL; +    return nullptr;    ProgramStateRef stateTrue, stateFalse; @@ -439,13 +443,13 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,    // Are the two values the same?    SValBuilder &svalBuilder = C.getSValBuilder();   -  llvm::tie(stateTrue, stateFalse) = +  std::tie(stateTrue, stateFalse) =      state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));    if (stateTrue && !stateFalse) {      // If the values are known to be equal, that's automatically an overlap.      emitOverlapBug(C, stateTrue, First, Second); -    return NULL; +    return nullptr;    }    // assume the two expressions are not equal. @@ -461,7 +465,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,    if (!reverseTest)      return state; -  llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); +  std::tie(stateTrue, stateFalse) = state->assume(*reverseTest);    if (stateTrue) {      if (stateFalse) {        // If we don't know which one comes first, we can't perform this test. @@ -506,12 +510,12 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,    if (!OverlapTest)      return state; -  llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); +  std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);    if (stateTrue && !stateFalse) {      // Overlap!      emitOverlapBug(C, stateTrue, First, Second); -    return NULL; +    return nullptr;    }    // assume the two expressions don't overlap. @@ -526,7 +530,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,      return;    if (!BT_Overlap) -    BT_Overlap.reset(new BugType(categories::UnixAPI, "Improper arguments")); +    BT_Overlap.reset(new BugType(Filter.CheckNameCStringBufferOverlap, +                                 categories::UnixAPI, "Improper arguments"));    // Generate a report for this bug.    BugReport *report =  @@ -548,7 +553,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,    // If a previous check has failed, propagate the failure.    if (!state) -    return NULL; +    return nullptr;    SValBuilder &svalBuilder = C.getSValBuilder();    BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); @@ -576,18 +581,19 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,                                                  *maxMinusRightNL, cmpTy);      ProgramStateRef stateOverflow, stateOkay; -    llvm::tie(stateOverflow, stateOkay) = +    std::tie(stateOverflow, stateOkay) =        state->assume(willOverflow.castAs<DefinedOrUnknownSVal>());      if (stateOverflow && !stateOkay) {        // We have an overflow. Emit a bug report.        ExplodedNode *N = C.generateSink(stateOverflow);        if (!N) -        return NULL; +        return nullptr;        if (!BT_AdditionOverflow) -        BT_AdditionOverflow.reset(new BuiltinBug("API", -          "Sum of expressions causes overflow")); +        BT_AdditionOverflow.reset( +            new BuiltinBug(Filter.CheckNameCStringOutOfBounds, "API", +                           "Sum of expressions causes overflow"));        // This isn't a great error message, but this should never occur in real        // code anyway -- you'd have to create a buffer longer than a size_t can @@ -600,7 +606,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,        BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N);        C.emitReport(report);         -      return NULL; +      return nullptr;      }      // From now on, assume an overflow didn't occur. @@ -703,8 +709,9 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,        if (ExplodedNode *N = C.addTransition(state)) {          if (!BT_NotCString) -          BT_NotCString.reset(new BuiltinBug(categories::UnixAPI, -            "Argument is not a null-terminated string.")); +          BT_NotCString.reset(new BuiltinBug( +              Filter.CheckNameCStringNotNullTerm, categories::UnixAPI, +              "Argument is not a null-terminated string."));          SmallString<120> buf;          llvm::raw_svector_ostream os(buf); @@ -714,8 +721,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,             << "', which is not a null-terminated string";          // Generate a report for this bug. -        BugReport *report = new BugReport(*BT_NotCString, -                                                          os.str(), N); +        BugReport *report = new BugReport(*BT_NotCString, os.str(), N);          report->addRange(Ex->getSourceRange());          C.emitReport(report);         @@ -763,8 +769,9 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,      if (ExplodedNode *N = C.addTransition(state)) {        if (!BT_NotCString) -        BT_NotCString.reset(new BuiltinBug(categories::UnixAPI, -          "Argument is not a null-terminated string.")); +        BT_NotCString.reset(new BuiltinBug( +            Filter.CheckNameCStringNotNullTerm, categories::UnixAPI, +            "Argument is not a null-terminated string."));        SmallString<120> buf;        llvm::raw_svector_ostream os(buf); @@ -795,7 +802,7 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,    // Get the memory region pointed to by the val.    const MemRegion *bufRegion = val.getAsRegion();    if (!bufRegion) -    return NULL;  +    return nullptr;    // Strip casts off the memory region.    bufRegion = bufRegion->StripCasts(); @@ -803,7 +810,7 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,    // Cast the memory region to a string region.    const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);    if (!strRegion) -    return NULL;  +    return nullptr;    // Return the actual string in the string region.    return strRegion->getStringLiteral(); @@ -845,7 +852,8 @@ ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,      }      return state->invalidateRegions(R, E, C.blockCount(), LCtx,  -                                    CausesPointerEscape, 0, 0, &ITraits); +                                    CausesPointerEscape, nullptr, nullptr, +                                    &ITraits);    }    // If we have a non-region value by chance, just remove the binding. @@ -909,7 +917,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,    QualType sizeTy = Size->getType();    ProgramStateRef stateZeroSize, stateNonZeroSize; -  llvm::tie(stateZeroSize, stateNonZeroSize) = +  std::tie(stateZeroSize, stateNonZeroSize) =      assumeZero(C, state, sizeVal, sizeTy);    // Get the value of the Dest. @@ -946,7 +954,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,      const char * const writeWarning =        "Memory copy function overflows destination buffer";      state = CheckBufferAccess(C, state, Size, Dest, Source, -                              writeWarning, /* sourceWarning = */ NULL); +                              writeWarning, /* sourceWarning = */ nullptr);      if (Restricted)        state = CheckOverlap(C, state, Size, Dest, Source); @@ -971,7 +979,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,        } else {          // If we don't know how much we copied, we can at least          // conjure a return value for later. -        SVal result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, +        SVal result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx,                                                            C.blockCount());          state = state->BindExpr(CE, LCtx, result);        } @@ -1066,7 +1074,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {    QualType sizeTy = Size->getType();    ProgramStateRef stateZeroSize, stateNonZeroSize; -  llvm::tie(stateZeroSize, stateNonZeroSize) = +  std::tie(stateZeroSize, stateNonZeroSize) =      assumeZero(C, state, sizeVal, sizeTy);    // If the size can be zero, the result will be 0 in that case, and we don't @@ -1092,7 +1100,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {      // See if they are the same.      DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);      ProgramStateRef StSameBuf, StNotSameBuf; -    llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); +    std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);      // If the two arguments might be the same buffer, we know the result is 0,      // and we only need to check one size. @@ -1113,7 +1121,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {        state = CheckBufferAccess(C, state, Size, Left, Right);        if (state) {          // The return value is the comparison result, which we don't know. -        SVal CmpV = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); +        SVal CmpV = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, +                                                 C.blockCount());          state = state->BindExpr(CE, LCtx, CmpV);          C.addTransition(state);        } @@ -1150,7 +1159,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,      SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);      ProgramStateRef stateZeroSize, stateNonZeroSize; -    llvm::tie(stateZeroSize, stateNonZeroSize) = +    std::tie(stateZeroSize, stateNonZeroSize) =        assumeZero(C, state, maxlenVal, maxlenExpr->getType());      // If the size can be zero, the result will be 0 in that case, and we don't @@ -1204,10 +1213,10 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,        ProgramStateRef stateStringTooLong, stateStringNotTooLong;        // Check if the strLength is greater than the maxlen. -      llvm::tie(stateStringTooLong, stateStringNotTooLong) = -          state->assume(C.getSValBuilder().evalBinOpNN( -              state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy) -                            .castAs<DefinedOrUnknownSVal>()); +      std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume( +          C.getSValBuilder() +              .evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy) +              .castAs<DefinedOrUnknownSVal>());        if (stateStringTooLong && !stateStringNotTooLong) {          // If the string is longer than maxlen, return maxlen. @@ -1223,7 +1232,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,        // no guarantee the full string length will actually be returned.        // All we know is the return value is the min of the string length        // and the limit. This is better than nothing. -      result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount()); +      result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, +                                                   C.blockCount());        NonLoc resultNL = result.castAs<NonLoc>();        if (strLengthNL) { @@ -1246,7 +1256,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,      // If we don't know the length of the string, conjure a return      // value, so it can be used in constraints, at least.      if (result.isUnknown()) { -      result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount()); +      result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, +                                                   C.blockCount());      }    } @@ -1349,7 +1360,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,    // - potential overflows caused by a bound that could exceed the destination    SVal amountCopied = UnknownVal();    SVal maxLastElementIndex = UnknownVal(); -  const char *boundWarning = NULL; +  const char *boundWarning = nullptr;    // If the function is strncpy, strncat, etc... it is bounded.    if (isBounded) { @@ -1371,7 +1382,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,        // Check if the max number to copy is less than the length of the src.        // If the bound is equal to the source length, strncpy won't null-        // terminate the result! -      llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume( +      std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(            svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)                .castAs<DefinedOrUnknownSVal>()); @@ -1418,7 +1429,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,          // case strncpy will do no work at all. Our bounds check uses n-1          // as the last element accessed, so n == 0 is problematic.          ProgramStateRef StateZeroSize, StateNonZeroSize; -        llvm::tie(StateZeroSize, StateNonZeroSize) = +        std::tie(StateZeroSize, StateNonZeroSize) =            assumeZero(C, state, *lenValNL, sizeTy);          // If the size is known to be zero, we're done. @@ -1629,7 +1640,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,    // If this is a stpcpy-style copy, but we were unable to check for a buffer    // overflow, we still need a result. Conjure a return value.    if (returnEnd && Result.isUnknown()) { -    Result = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); +    Result = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());    }    // Set the return value. @@ -1711,7 +1722,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,    SValBuilder &svalBuilder = C.getSValBuilder();    DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);    ProgramStateRef StSameBuf, StNotSameBuf; -  llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); +  std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);    // If the two arguments might be the same buffer, we know the result is 0,    // and we only need to check one size. @@ -1786,7 +1797,8 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,    if (!canComputeResult) {      // Conjure a symbolic value. It's the best we can do. -    SVal resultVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); +    SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, +                                                  C.blockCount());      state = state->BindExpr(CE, LCtx, resultVal);    } @@ -1843,7 +1855,7 @@ void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const {    } else {      assert(SearchStrVal.isUnknown());      // Conjure a symbolic value. It's the best we can do. -    Result = SVB.conjureSymbolVal(0, CE, LCtx, C.blockCount()); +    Result = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());    }    // Set the return value, and finish. @@ -1863,7 +1875,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {      return false;    // FIXME: Poorly-factored string switches are slow. -  FnCheck evalFunction = 0; +  FnCheck evalFunction = nullptr;    if (C.isCLibraryFunction(FDecl, "memcpy"))      evalFunction =  &CStringChecker::evalMemcpy;    else if (C.isCLibraryFunction(FDecl, "mempcpy")) @@ -1907,7 +1919,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {    // Make sure each function sets its own description.    // (But don't bother in a release build.) -  assert(!(CurrentFunctionDescription = NULL)); +  assert(!(CurrentFunctionDescription = nullptr));    // Check and evaluate the call.    (this->*evalFunction)(C, CE); @@ -1928,9 +1940,8 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {    // Record string length for char a[] = "abc";    ProgramStateRef state = C.getState(); -  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); -       I != E; ++I) { -    const VarDecl *D = dyn_cast<VarDecl>(*I); +  for (const auto *I : DS->decls()) { +    const VarDecl *D = dyn_cast<VarDecl>(I);      if (!D)        continue; @@ -2057,10 +2068,12 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,    C.addTransition(state);  } -#define REGISTER_CHECKER(name) \ -void ento::register##name(CheckerManager &mgr) {\ -  mgr.registerChecker<CStringChecker>()->Filter.Check##name = true; \ -} +#define REGISTER_CHECKER(name)                                                 \ +  void ento::register##name(CheckerManager &mgr) {                             \ +    CStringChecker *checker = mgr.registerChecker<CStringChecker>();           \ +    checker->Filter.Check##name = true;                                        \ +    checker->Filter.CheckName##name = mgr.getCurrentCheckName();               \ +  }  REGISTER_CHECKER(CStringNullArg)  REGISTER_CHECKER(CStringOutOfBounds)  | 
