Skip to content

Commit abe26fd

Browse files
authored
Fix stubs for function pointers (closes #462) (#565)
1 parent a6fc993 commit abe26fd

18 files changed

+201
-69
lines changed

server/src/Tests.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "printers/TestsPrinter.h"
66
#include "utils/KleeUtils.h"
77
#include "utils/StringUtils.h"
8+
#include "utils/StubsUtils.h"
89

910
#include "loguru.h"
1011

@@ -31,7 +32,9 @@ Tests::MethodDescription::MethodDescription()
3132
{ Tests::ERROR_SUITE_NAME, std::vector<int>() }},
3233
codeText{{ Tests::DEFAULT_SUITE_NAME, std::string() },
3334
{ Tests::ERROR_SUITE_NAME, std::string() }},
34-
modifiers{} { }
35+
modifiers{} {
36+
stubsStorage = std::make_shared<StubsStorage>();
37+
}
3538

3639
static const std::unordered_map<std::string, std::string> FPSpecialValuesMappings = {
3740
{"nan", "NAN"},
@@ -201,13 +204,13 @@ std::shared_ptr<ArrayValueView> KTestObjectParser::multiArrayView(const std::vec
201204
std::shared_ptr<FunctionPointerView> KTestObjectParser::functionPointerView(const std::optional<std::string> &scopeName,
202205
const std::string &methodName, const std::string &paramName) {
203206
std::string value =
204-
PrinterUtils::getFunctionPointerStubName(scopeName, methodName, paramName).substr(1);
207+
StubsUtils::getFunctionPointerStubName(scopeName, methodName, paramName).substr(1);
205208
return std::make_shared<FunctionPointerView>(value);
206209
}
207210

208211
std::shared_ptr<FunctionPointerView> KTestObjectParser::functionPointerView(const std::string &structName,
209212
const std::string &fieldName) {
210-
std::string value = PrinterUtils::getFunctionPointerAsStructFieldStubName(structName, fieldName, false).substr(1);
213+
std::string value = StubsUtils::getFunctionPointerAsStructFieldStubName(structName, fieldName, false).substr(1);
211214
return std::make_shared<FunctionPointerView>(value);
212215
}
213216

@@ -677,14 +680,10 @@ types::Type KTestObjectParser::traverseLazyInStruct(std::vector<bool> &visited,
677680
void KTestObjectParser::assignTypeStubVar(Tests::MethodTestCase &testCase,
678681
const Tests::MethodDescription &methodDescription) {
679682
for (auto const &obj : testCase.objects) {
680-
if (StringUtils::endsWith(obj.name, PrinterUtils::KLEE_SYMBOLIC_SUFFIX)) {
681-
std::string stubFuncName = obj.name.substr(0, obj.name.length() - PrinterUtils::KLEE_SYMBOLIC_SUFFIX.length());
682-
if (!CollectionUtils::contains(methodDescription.functionPointers, stubFuncName)) {
683-
std::string message = "Can't find function pointer with name " + stubFuncName;
684-
LOG_S(WARNING) << message;
685-
continue;
686-
}
687-
types::Type stubType = types::Type::createArray(methodDescription.functionPointers.at(stubFuncName)->returnType);
683+
std::optional<std::shared_ptr<FunctionInfo>> maybeFunctionInfo =
684+
methodDescription.stubsStorage->getFunctionPointerByKTestObjectName(obj.name);
685+
if (maybeFunctionInfo.has_value()) {
686+
types::Type stubType = types::Type::createArray(maybeFunctionInfo.value()->returnType);
688687
std::shared_ptr<AbstractValueView> stubView = testParameterView({obj.name, obj.bytes}, {stubType, obj.name},
689688
PointerUsage::PARAMETER, testCase.lazyAddressToName,
690689
testCase.lazyReferences, methodDescription);

server/src/Tests.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <tsl/ordered_map.h>
1515
#include <tsl/ordered_set.h>
1616
#include "Paths.h"
17+
#include "stubs/StubsStorage.h"
1718

1819
#include <cassert>
1920
#include <climits>
@@ -498,6 +499,8 @@ namespace tests {
498499

499500
typedef std::unordered_map<std::string, std::shared_ptr<types::FunctionInfo>> FPointerMap;
500501
FPointerMap functionPointers;
502+
std::shared_ptr<StubsStorage> stubsStorage;
503+
501504
std::vector<MethodTestCase> testCases;
502505
typedef std::unordered_map<std::string, std::vector<int>> SuiteNameToTestCasesMap;
503506
SuiteNameToTestCasesMap suiteTestCases;

server/src/printers/KleeConstraintsPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "KleeConstraintsPrinter.h"
22

33
#include "utils/PrinterUtils.h"
4+
#include "utils/StubsUtils.h"
45
#include "exceptions/UnImplementedException.h"
56

67
#include "loguru.h"
@@ -125,7 +126,7 @@ void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &sta
125126
field.type,
126127
isStruct ? state.endString : false,
127128
state.depth + 1 };
128-
std::string stubFunctionName = PrinterUtils::getFunctionPointerAsStructFieldStubName(curStruct.name, field.name);
129+
std::string stubFunctionName = StubsUtils::getFunctionPointerAsStructFieldStubName(curStruct.name, field.name);
129130
switch (typesHandler->getTypeKind(field.type)) {
130131
case TypeKind::STRUCT_LIKE:
131132
genConstraintsForStruct(newState);

server/src/printers/KleePrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "utils/CollectionUtils.h"
99
#include "utils/FileSystemUtils.h"
1010
#include "utils/KleeUtils.h"
11+
#include "utils/StubsUtils.h"
1112
#include "visitors/KleeAssumeParamVisitor.h"
1213
#include "visitors/KleeAssumeReturnValueVisitor.h"
1314

@@ -396,7 +397,7 @@ void KleePrinter::genParamsDeclarations(
396397
bool KleePrinter::genParamDeclaration(const Tests::MethodDescription &testMethod,
397398
const Tests::MethodParam &param) {
398399
std::string stubFunctionName =
399-
PrinterUtils::getFunctionPointerStubName(testMethod.isClassMethod() ? std::make_optional(testMethod.classObj->name) : std::nullopt,
400+
StubsUtils::getFunctionPointerStubName(testMethod.isClassMethod() ? std::make_optional(testMethod.classObj->name) : std::nullopt,
400401
testMethod.name, param.name);
401402
if (types::TypesHandler::isPointerToFunction(param.type)) {
402403
strDeclareVar(getTypedefFunctionPointer(testMethod.name, param.name, false), param.name,

server/src/printers/Printer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "types/SimpleType.h"
55
#include "utils/ArgumentsUtils.h"
66
#include "utils/Copyright.h"
7+
#include "utils/StubsUtils.h"
78
#include "visitors/VerboseParameterVisitor.h"
89
#include "printers/KleeConstraintsPrinter.h"
910

@@ -549,8 +550,8 @@ namespace printer {
549550
std::string scopeName = (forKlee ? testMethod.getClassName().value_or("") : "");
550551
std::string prefix = PrinterUtils::getKleePrefix(forKlee);
551552
for (const auto &[name, pointerFunctionStub] : testMethod.functionPointers) {
552-
std::string stubName = PrinterUtils::getFunctionPointerStubName(scopeName,
553-
testMethod.name, name, true);
553+
std::string stubName = StubsUtils::getFunctionPointerStubName(scopeName, testMethod.name, name, true);
554+
testMethod.stubsStorage->registerFunctionPointerStub(testMethod.name, pointerFunctionStub);
554555
writeStubForParam(typesHandler, pointerFunctionStub, testMethod.name, stubName, true,
555556
forKlee);
556557
}

server/src/printers/TestsPrinter.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "visitors/VerboseAssertsReturnValueVisitor.h"
1010
#include "visitors/VerboseParameterVisitor.h"
1111
#include "utils/KleeUtils.h"
12+
#include "utils/StubsUtils.h"
1213

1314
#include "loguru.h"
1415

@@ -452,20 +453,27 @@ void TestsPrinter::verboseParameters(const Tests::MethodDescription &methodDescr
452453
ss << NL;
453454
}
454455

455-
if (!testCase.stubValuesTypes.empty()) {
456-
strComment("Initialize symbolic stubs");
457-
for (auto i = 0; i < testCase.stubValuesTypes.size(); i++) {
458-
const auto &param = testCase.stubValuesTypes[i];
459-
const auto &value = testCase.stubValues[i];
460-
if (param.type.isTwoDimensionalPointer()) {
461-
Tests::MethodParam valueParam{ param.type, param.underscoredName(), param.alignment };
462-
verboseParameter(methodDescription, valueParam, value, true);
463-
gen2DPointer(param, false);
464-
} else {
465-
verboseParameter(methodDescription, param, value, false);
456+
std::vector<std::vector<tests::Tests::MethodParam>> types = { testCase.stubValuesTypes, testCase.stubParamTypes };
457+
std::vector<std::vector<tests::Tests::TestCaseParamValue>> values = { testCase.stubParamValues, testCase.stubParamValues };
458+
459+
for (int j = 0; j < types.size(); j++) {
460+
if (!types[j].empty()) {
461+
if (j == 0) {
462+
strComment("Initialize symbolic stubs");
463+
}
464+
for (auto i = 0; i < types[j].size(); i++) {
465+
const auto &param = types[j][i];
466+
const auto &value = values[j][i];
467+
if (param.type.isTwoDimensionalPointer()) {
468+
Tests::MethodParam valueParam{ param.type, param.underscoredName(), param.alignment };
469+
verboseParameter(methodDescription, valueParam, value, true);
470+
gen2DPointer(param, false);
471+
} else {
472+
verboseParameter(methodDescription, param, value, false);
473+
}
466474
}
475+
ss << NL;
467476
}
468-
ss << NL;
469477
}
470478

471479
if (!testCase.paramValues.empty()) {
@@ -488,7 +496,7 @@ void TestsPrinter::printFunctionParameters(const Tests::MethodDescription &metho
488496
Tests::TestCaseParamValue value = testCase.paramValues[i];
489497
Tests::MethodParam valueParam = getValueParam(param);
490498
value.name = valueParam.name;
491-
if (param.type.isLValueReference() || param.type.isSimple()) {
499+
if (param.type.isLValueReference() || param.type.isSimple() || param.type.isPointerToFunction()) {
492500
verboseParameter(methodDescription, valueParam, value, true);
493501
}
494502
}
@@ -499,9 +507,8 @@ void TestsPrinter::verboseParameter(const Tests::MethodDescription &method,
499507
const Tests::MethodParam &param,
500508
const Tests::TestCaseParamValue &value,
501509
bool needDeclaration) {
502-
std::string stubFunctionName =
503-
PrinterUtils::getFunctionPointerStubName(method.getClassTypeName(),
504-
method.name, param.name);
510+
std::string stubFunctionName = StubsUtils::getFunctionPointerStubName(method.getClassTypeName(),
511+
method.name, param.name);
505512
if (types::TypesHandler::isPointerToFunction(param.type)) {
506513
strDeclareVar(getTypedefFunctionPointer(method.name, param.name, false), param.name,
507514
stubFunctionName);
@@ -659,7 +666,7 @@ void TestsPrinter::printPointerParameter(const Tests::MethodDescription &methodD
659666
const auto &value = testCase.paramValues[param_num];
660667
if (types::TypesHandler::isArrayOfPointersToFunction(param.type)) {
661668
auto type = getTypedefFunctionPointer(methodDescription.name, param.name, false);
662-
std::string stubName = PrinterUtils::getFunctionPointerStubName(
669+
std::string stubName = StubsUtils::getFunctionPointerStubName(
663670
methodDescription.getClassTypeName(), methodDescription.name, param.name);
664671
strDeclareArrayOfFunctionPointerVar(type, param.name, stubName);
665672
} else if (types::TypesHandler::isCStringType(param.type)) {

server/src/stubs/StubsStorage.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "StubsStorage.h"
2+
3+
#include <utility>
4+
#include "utils/StubsUtils.h"
5+
6+
void StubsStorage::registerFunctionPointerStub(const std::string &methodName, std::shared_ptr<types::FunctionInfo> functionInfo) {
7+
_functionPointers[StubsUtils::getStubSymbolicVarName(methodName + "_" + functionInfo->name)] = std::move(functionInfo);
8+
}
9+
10+
std::optional<std::shared_ptr<types::FunctionInfo>>
11+
StubsStorage::getFunctionPointerByKTestObjectName(const std::string &objectName) {
12+
return CollectionUtils::getOptionalValue(_functionPointers, objectName);
13+
}

server/src/stubs/StubsStorage.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef UTBOTCPP_STUBSSTORAGE_H
2+
#define UTBOTCPP_STUBSSTORAGE_H
3+
4+
#include <string>
5+
#include <unordered_map>
6+
#include <memory>
7+
8+
#include "types/Types.h"
9+
10+
class StubsStorage {
11+
public:
12+
void registerFunctionPointerStub(const std::string &methodName, std::shared_ptr<types::FunctionInfo>);
13+
std::optional<std::shared_ptr<types::FunctionInfo>> getFunctionPointerByKTestObjectName(const std::string &objectName);
14+
private:
15+
std::unordered_map<std::string, std::shared_ptr<types::FunctionInfo>> _functionPointers;
16+
};
17+
18+
19+
#endif //UTBOTCPP_STUBSSTORAGE_H

server/src/utils/PrinterUtils.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,31 +62,6 @@ namespace PrinterUtils {
6262
return LAZYRENAME + std::to_string(cnt);
6363
}
6464

65-
std::string getFunctionPointerStubName(const std::optional<std::string> &scopeName,
66-
const std::string &methodName,
67-
const std::string &paramName,
68-
bool omitSuffix) {
69-
std::string stubName = "*" + scopeName.value_or("") + "_" + methodName;
70-
if (!omitSuffix) {
71-
stubName += "_" + paramName + "_stub";
72-
} else {
73-
stubName = stubName.substr(1);
74-
}
75-
return stubName;
76-
}
77-
78-
std::string getFunctionPointerAsStructFieldStubName(const std::string &structName,
79-
const std::string &fieldName,
80-
bool omitSuffix) {
81-
std::string stubName = "*" + structName;
82-
if (!omitSuffix) {
83-
stubName += "_" + fieldName + "_stub";
84-
} else {
85-
stubName = stubName.substr(1);
86-
}
87-
return stubName;
88-
}
89-
9065
std::string getKleePrefix(bool forKlee) {
9166
return forKlee ? "klee_" : "";
9267
}

server/src/utils/PrinterUtils.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,6 @@ namespace PrinterUtils {
7272

7373
std::string fillVarName(std::string const &temp, std::string const &varName);
7474

75-
std::string getFunctionPointerStubName(const std::optional<std::string> &scopeName,
76-
const std::string &methodName,
77-
const std::string &paramName,
78-
bool omitSuffix = false);
79-
80-
std::string getFunctionPointerAsStructFieldStubName(const std::string &structName,
81-
const std::string &fieldName,
82-
bool omitSuffix = false);
83-
8475
std::string getKleePrefix(bool forKlee);
8576

8677
std::string wrapUserValue(const testsgen::ValidationType &type, const std::string &value);

server/src/utils/StubsUtils.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "StubsUtils.h"
2+
#include "PrinterUtils.h"
3+
4+
namespace StubsUtils {
5+
std::string getFunctionPointerStubName(const std::optional<std::string> &scopeName,
6+
const std::string &methodName,
7+
const std::string &paramName,
8+
bool omitSuffix) {
9+
std::string stubName = "*" + scopeName.value_or("") + "_" + methodName;
10+
if (!omitSuffix) {
11+
stubName += "_" + paramName + "_stub";
12+
} else {
13+
stubName = stubName.substr(1);
14+
}
15+
return stubName;
16+
}
17+
18+
std::string getStubSymbolicVarName(const std::string &methodName) {
19+
return methodName + PrinterUtils::KLEE_SYMBOLIC_SUFFIX;
20+
}
21+
22+
std::string getFunctionPointerAsStructFieldStubName(const std::string &structName,
23+
const std::string &fieldName,
24+
bool omitSuffix) {
25+
std::string stubName = "*" + structName;
26+
if (!omitSuffix) {
27+
stubName += "_" + fieldName + "_stub";
28+
} else {
29+
stubName = stubName.substr(1);
30+
}
31+
return stubName;
32+
}
33+
}

server/src/utils/StubsUtils.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef UTBOTCPP_STUBUTILS_H
2+
#define UTBOTCPP_STUBUTILS_H
3+
4+
#include <string>
5+
#include <optional>
6+
7+
namespace StubsUtils {
8+
std::string getFunctionPointerStubName(const std::optional<std::string> &scopeName,
9+
const std::string &methodName,
10+
const std::string &paramName,
11+
bool omitSuffix = false);
12+
13+
std::string getStubSymbolicVarName(const std::string &methodName);
14+
15+
std::string getFunctionPointerAsStructFieldStubName(const std::string &structName,
16+
const std::string &fieldName,
17+
bool omitSuffix = false);
18+
}
19+
20+
#endif //UTBOTCPP_STUBUTILS_H

server/src/visitors/FunctionPointerForStubsVisitor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "printers/Printer.h"
44

55
#include <unordered_set>
6+
#include "utils/StubsUtils.h"
67

78
namespace visitor {
89
FunctionPointerForStubsVisitor::FunctionPointerForStubsVisitor(const types::TypesHandler *typesHandler)
@@ -38,8 +39,7 @@ namespace visitor {
3839
}
3940
auto structInfo = typesHandler->getStructInfo(type);
4041
for (const auto &[name, field] : structInfo.functionFields) {
41-
auto stubName =
42-
PrinterUtils::getFunctionPointerAsStructFieldStubName(structInfo.name, name, true);
42+
auto stubName = StubsUtils::getFunctionPointerAsStructFieldStubName(structInfo.name, name, true);
4343
printer.writeStubForParam(typesHandler, field, structInfo.name, stubName, false, true);
4444
}
4545
for (auto &field : structInfo.fields) {

0 commit comments

Comments
 (0)