How to taint the command line arguments in Clang Static Analyzer - c++

In Clang Static Analyzer, I have the ability to taint any SVal I am interested in. However, I wonder how could I taint the command line arguments. A simple example here:
int main(int argc, char **argv)
{
memcpy(xxx,argv[0],xxx);
}
Because there is no caller to main function, so I can't use precall or postcall the get the SVal of argv as well as callExpr. I think clang must have provided such a interface to get the top frame function's arguments.How could I get it? beginfunction is the only hook function that would be invoked at the start of top frame function, but the only argument clang pass to us is CheckerContext. I try to get the SVal from it, but failed.

Problem solved! I hook the beginfunction and the code is
StoreManager & store = C.getStoreManager();
const ParmVarDecl *pdecl = C.getCurrentAnalysisDeclContext()->getDecl()->getAsFunction()->getParamDecl(0);
const Loc loc = store.getLValueVar(pdecl,C.getLocationContext());
ProgramStateRef state = C.getState();
Store s = state->getStore();
store.getBinding(s,loc).dump();
Here I get the SVal of the first argument of the top frame function.

Related

Writing a Clang-Tidy check, how do I find if a pointer is initialized before it is called?

I am trying to port some static checks from an old in-house C++ static checker to clang-tidy.
Since I am really new to this tool, I am having a really hard time doing it and I am starting to think that it's not the proper tool to do what I want.
So basically what I am currently trying to implement, is a check on pointer initialization. I want to verify that a local pointer is properly initialized before being used.
For example if I take this sample of code:
void method(const char *);
int main(int argc, char **argv){
const char * ptNotInit;
const char * ptInit = "hello";
method(ptNotInit);
method(ptInit);
return 0;
}
I want to get an error on method(ptNotInit) because I am passing a nullptr to method.
At first I try a very simple matcher:
Finder->addMatcher(varDecl(hasType(pointerType())).bind("pointerDeclaration"),this);
// and
const auto *MatchedPtDecl = Result.Nodes.getNodeAs<VarDecl>("pointerDeclaration");
if ( MatchedPtDecl->hasInit() == false )
// Do an error
So i get an error on ptNotInit and argv, so I add MatchedPtDecl->isLocalVarDecl() and all seems fine.
Except that in my code sample I add:
ptNotInit = "Hello again";
method(ptNotInit);
I still get an error on ptNotInit when I abviously initialized it just before the call to method.
I suppose that the VarDecl method hasInit() just apply for the declaration of the variable, explaining why it return false?
So my question is, how can I know when calling method(ptNotInit) if ptNotInit was initialized?
Clang-tidy seems powerful to find something, but I don't know how to find the lack of something, if you see what I mean...
I try to write more complex matcher to find init like this one
Finder->addMatcher(binaryOperator(hasOperatorName("="),hasLHS(declRefExpr(hasType(pointerType()),hasDeclaration(varDecl().bind("pointerDeclaration"))).bind("affectation")))
If my pointer is on the left of an = operator, that should be an initialization... Ok why not, but at the end I want to know that there are no initialization, I don't want to match initialization syntax... Maybe I am taking the problem backward.
Any tips would help, or if you can point me to an already implemented checker doing something similar, that would be a great help!

C++/Tcl Can I retrieve Tcl file line number when a function recorded by Tcl_CreateCommand is invoked

I run a Tcl script from a C++ program using Tcl_EvalFile. I defined some custom commands (using Tcl_CreateCommand), so when they are found in the file a callback is called and then I can run some C++ code (TclInvokeStringCommand invokes the callback given to Tcl_CreateCommand, the callback type is int (*executeCmd)( ClientData data, Tcl_Interp *interp, int argc, const char *argv[] )).
I want to know the script file name and line number within the callback function being invoked.
I could get the script file name using ((Interp*) interp)->scriptFile.
However, I could not get the script file line number. Is there a way to retrieve this (or compute it in any way)?
The information is only exposed at the Tcl level via the info frame command. (The internal C API for it is sufficiently horrible that it's never been made public.) This means you need to do something like this with Tcl_Eval():
// These can be cached safely per thread; reference management is a thing for another question
Tcl_Obj *scriptNameHandle = Tcl_NewStringObj("file", -1);
Tcl_Obj *lineNumberHandle = Tcl_NewStringObj("line", -1);
// How to actually get the information; I'm omitting error handling
Tcl_Eval(interp, "info frame -1");
Tcl_Obj *frameDict = Tcl_GetObjResult(interp);
Tcl_Obj *scriptNameObj = nullptr, *lineNumberObj = nullptr;
Tcl_DictObjGet(nullptr, frameDict, scriptNameHandle, &scriptNameObj);
Tcl_DictObjGet(nullptr, frameDict, lineNumberHandle, &lineNumberObj);
// Now we have to unbox the information
if (scriptNameObj != nullptr) {
const char *filename = Tcl_GetString(scriptNameObj);
// Do something with this info; COPY IT if you want to keep past the result reset
}
if (lineNumberObj != nullptr) {
int lineNumber = -1;
Tcl_GetIntFromObj(nullptr, lineNumberObj, &lineNumber);
// Do something with this info
}
// Release the result memory, i.e., the dictionary and its contents
Tcl_ResetResult(interp);
Note that neither the file nor the line keys are guaranteed to be present; the line key is usually there, but the file key is only there when running code that can be tracked back to a file, i.e., back to Tcl_EvalFile() and related.

How to force gtest write report to xml from Init

For some reason, I can't start gtest tests from commandline, so I can't pass any arguments to it. I want to run InitGoogleTest already with a parameter defined in code.
Somewhere on the Internet I found a solution like this:
int main(int argc, char **argv) {
char *option[] = { "test.exe", //it doesn't have meaning, just dummy
"--gtest_output=xml:filename" };
int argc1 = 2;
::testing::InitGoogleTest(&argc1, option);
return RUN_ALL_TESTS();
}
This solution didn't produce any errors but didn't create any xml with report either.
Can anyone suggest how to force gtest to write xml from Init?
You can override the output flag by adding
::testing::GTEST_FLAG(output) = "xml:filename";
before the call to InitGoogleTest. You can read more on it at Google Test docs.

Using gtest specific parameters inside the testcase

Im using gtest as the test framework for my project and I need to use the following parameter value which is passed as a gtest parameter, inside the test case
./gtest_bin --gtest_repeat=5
Currently what I'm doing is, I've created a custom Listener extended from "EmptyTestEventListener" and pass the iteration value to a global variable when the callback to the following function is received as following,
customListener class
class customListener : public testing::EmptyTestEventListener
{
customListener(int *iteration) : m_iteration(iteration) {}
virtual void OnTestIterationStart(const testing::UnitTest& unit_test, int iteration)
{
*m_iteration = iteration;
}
}
main
int g_iteration;
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
if(argc > 1)
g_array_length = atoi(argv[1]);
testing::TestEventListeners& listners = testing::UnitTest::GetInstance()->listeners();
listners.Append(new printers::customListener(&g_iteration));
return RUN_ALL_TESTS();
}
Is there an easier way to get this gtest parameter value?
If generalized, Is there a way to get any gtest specific parameter value that can used inside a testcase?
IMPORTANT NOTE
Please use with great care - as this is not documented feature and
might be changed (i.e. it might stop working) in next gtest/gmock
versions.
You can access any flag by ::testing::GTEST_FLAG(flag_name) - in your case - ::testing::GTEST_FLAG(repeat).
I got this information indirectly from this manual and by examining gtest.h file.

Creating a program in C++ that takes arguements from the command line

I am trying to learn how to make a program in C++ that when you run it, you can tell it to run and specify options all in one line. For example you can do ipconfig /all in CMD and it runs ipconfig.exe with the option /all. Another example would be shutdown -f which tells the computer to shutdown with the option -f. For example, I want to make a program that downloads something from a URL and call it for example downloader. From command line one would type downloader http://filehere.com /h which would download the file with the /h option which I would define its property in my program. I don't want code or guides on how to make a downloader I am just trying to learn how to specify options like the /h. Are there any guides out there that you know of and could post or any sample code? I have tried searching for guides, but I think I just don't know what this operation is actually called. Thank you.
You typically define your main function to take two arguments: int argc and char *argv[], such as:
int
main(int argc, char *argv[])
{
...
The first argument is how many parameters your program received, argv is a pointer to them. Note, this isn't mandated, you can name them whatever you want, but that's the convention. Just make sure your types match up.
You can use an option-parsing library, but those are often OS-specific. One simple way to check if you received a /h is:
int got_h = 0;
for (int i=0; i<argc; ++i)
if (strcmp(argv[i], "/h") == 0)
got_h = 1;
...
if (got_h)
...
argv[argc] will always be NULL to make iterating through them easier.
Some more information here: http://www.site.uottawa.ca/~lucia/courses/2131-05/labs/Lab3/CommandLineArguments.html
The main function takes two arguments, traditionally named argc and argv:
int main (int argc, char * argv[])
{
// ...
}
argc contains the number of arguments passed on the command line, and the argv array contains such arguments (with argv[0] being the name used to invoke your program); the last element of the argv array (i.e. argv[argc]) contains a NULL pointer.
Depending upon your proficiency and inclination to use pointers, you may prefer to capture the command line as a vector<string>:
// UNTESTED CODE
int main(int argc, char **argv) {
std::vector<std::string> args(argv+1, argv+argc);
if(args.empty()) {
std::cout << "Usage: downloader URL [options]\n";
return 1;
}
if(std::find(args.begin(), args.end(), "/h") != args.end()) {
option_h = true;
}
Download(args[0]);
}