@@ -1804,3 +1804,94 @@ void CheckBufferOverrun::writeOutsideBufferSizeError(const Token *tok, const std
18041804 " The number of bytes to write (" + MathLib::toString (writeLength) + " bytes) are bigger than the source buffer (" +MathLib::toString (stringLength)+ " bytes)."
18051805 " Please check the second and the third parameter of the function '" +strFunctionName+" '." );
18061806}
1807+
1808+ Check::FileInfo* CheckBufferOverrun::getFileInfo (const Tokenizer *tokenizer) const
1809+ {
1810+ MyFileInfo *fileInfo = new MyFileInfo;
1811+
1812+ // Array usage..
1813+ const SymbolDatabase* const symbolDatabase = tokenizer->getSymbolDatabase ();
1814+ const std::size_t functions = symbolDatabase->functionScopes .size ();
1815+ for (std::size_t i = 0 ; i < functions; ++i) {
1816+ const Scope * const scope = symbolDatabase->functionScopes [i];
1817+ for (const Token *tok = scope->classStart ; tok && tok != scope->classEnd ; tok = tok->next ()) {
1818+ if (Token::Match (tok, " %var% [" ) &&
1819+ Token::Match (tok->linkAt (1 ), " ] !![" ) &&
1820+ tok->variable () &&
1821+ tok->variable ()->isExtern () &&
1822+ tok->variable ()->isGlobal () &&
1823+ tok->next ()->astOperand2 ()) {
1824+ const ValueFlow::Value *value = tok->next ()->astOperand2 ()->getMaxValue (false );
1825+ if (value && value->intvalue > 0 ) {
1826+ struct MyFileInfo ::ArrayUsage arrayUsage;
1827+ arrayUsage.index = value->intvalue ;
1828+ arrayUsage.fileName = tokenizer->list .file (tok);
1829+ arrayUsage.linenr = tok->linenr ();
1830+ std::map<std::string, struct MyFileInfo ::ArrayUsage>::iterator it = fileInfo->arrayUsage .find (tok->str ());
1831+ if (it == fileInfo->arrayUsage .end () || it->second .index < arrayUsage.index )
1832+ fileInfo->arrayUsage [tok->str ()] = arrayUsage;
1833+ }
1834+ }
1835+ }
1836+ }
1837+
1838+ // Arrays..
1839+ const std::list<Variable> &varlist = symbolDatabase->scopeList .front ().varlist ;
1840+ for (std::list<Variable>::const_iterator it = varlist.begin (); it != varlist.end (); ++it) {
1841+ const Variable &var = *it;
1842+ if (!var.isStatic () && var.isArray () && var.dimensions ().size () == 1U )
1843+ fileInfo->arraySize [var.name ()] = var.dimension (0U );
1844+ }
1845+
1846+ return fileInfo;
1847+ }
1848+
1849+ void CheckBufferOverrun::analyseWholeProgram (const std::list<Check::FileInfo*> &fileInfo, ErrorLogger &errorLogger)
1850+ {
1851+ // Merge all fileInfo
1852+ MyFileInfo all;
1853+ for (std::list<Check::FileInfo*>::const_iterator it = fileInfo.begin (); it != fileInfo.end (); ++it) {
1854+ const MyFileInfo *fi = dynamic_cast <MyFileInfo*>(*it);
1855+ if (!fi)
1856+ continue ;
1857+
1858+ // merge array usage
1859+ for (std::map<std::string, struct MyFileInfo ::ArrayUsage>::const_iterator it2 = fi->arrayUsage .begin (); it2 != fi->arrayUsage .end (); ++it2) {
1860+ std::map<std::string, struct MyFileInfo ::ArrayUsage>::const_iterator allit = all.arrayUsage .find (it2->first );
1861+ if (allit == all.arrayUsage .end () || it2->second .index > allit->second .index )
1862+ all.arrayUsage [it2->first ] = it2->second ;
1863+ }
1864+
1865+ // merge array info
1866+ for (std::map<std::string, MathLib::bigint>::const_iterator it2 = fi->arraySize .begin (); it2 != fi->arraySize .end (); ++it2) {
1867+ std::map<std::string, MathLib::bigint>::const_iterator allit = all.arraySize .find (it2->first );
1868+ if (allit == all.arraySize .end ())
1869+ all.arraySize [it2->first ] = it2->second ;
1870+ else
1871+ all.arraySize [it2->first ] = -1 ;
1872+ }
1873+ }
1874+
1875+ // Check buffer usage
1876+ for (std::map<std::string, struct MyFileInfo ::ArrayUsage>::const_iterator it = all.arrayUsage .begin (); it != all.arrayUsage .end (); ++it) {
1877+ std::map<std::string, MathLib::bigint>::const_iterator sz = all.arraySize .find (it->first );
1878+ if (sz != all.arraySize .end () && sz->second > 0 && sz->second < it->second .index ) {
1879+ ErrorLogger::ErrorMessage::FileLocation fileLoc;
1880+ fileLoc.setfile (it->second .fileName );
1881+ fileLoc.line = it->second .linenr ;
1882+
1883+ std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
1884+ locationList.push_back (fileLoc);
1885+
1886+ std::ostringstream ostr;
1887+ ostr << " Array " << it->first << ' [' << sz->second << " ] accessed at index " << it->second .index << " which is out of bounds" ;
1888+
1889+ const ErrorLogger::ErrorMessage errmsg (locationList,
1890+ Severity::error,
1891+ ostr.str (),
1892+ " arrayIndexOutOfBounds" ,
1893+ false );
1894+ errorLogger.reportErr (errmsg);
1895+ }
1896+ }
1897+ }
0 commit comments