Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clang static analyzer: potential memory leaks and unitialized values #6

Closed
floooh opened this issue Jul 11, 2015 · 3 comments
Closed

Comments

@floooh
Copy link
Contributor

floooh commented Jul 11, 2015

When running the code through the clang static analyzer (for instance in Xcode -> Product -> Analyzer), there's a small number of warnings (mostly uncritical like 'Values stored to X is never read'), but there are a couple of more critical warning in glslangValidator/StandAlone.cpp where memory is not freed, and a function is potentially called with an unitialized value (very likely a false positive because the code should return, but easy to fix).

Here's a list of the critical warnings (everything that is not a 'is never read' warning):

Potential leak of memory pointed to by 'config' in StandAlone.cpp/ProcessConfigFile():

If there's no config file given, a default 'config' is used which is allocated here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L239, the static analyzer thinks that is is never freed.

Apart from that warning, there are several allocations happening in ReadFileData(), which don't seem to have a corresponding free() call (for instance here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L965.

Also in FreeFileData() it looks like only the 'node pointers' are freed, not the array that contains the pointers allocated here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L953

Potential leak of memory pointed to by 'program':

The object created here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L619

...is not deleted when this if is taken: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L627

Potential leak of memory pointed to by 'return_data':

The memory allocated here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L953

Is not freed when this 'if' is taken: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L956

Function call argument is an unitialized value:

This is very likely a false positive, but easy to fix: clang analyzer says that the 'FILE* in' here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L948

...can remain unitialized if the call to fopen_s returns with an error when fgetc() is called here: https://github.com/KhronosGroup/glslang/blob/master/StandAlone/StandAlone.cpp#L960

This is the list of 'Value stored in X is never read', some of these may point to actual bugs, not sure:

Value stored to 'ch' is never read:

https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/preprocessor/PpContext.h#L411

Value stored to 'fragOutHasLocation' is never read:

https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/linkValidate.cpp#L557

Value stored to 'token' is never read:

https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/preprocessor/Pp.cpp#L831

Value stored to 'isVersion' is never read:

https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/preprocessor/Pp.cpp#L867

Value stored to 'exp' is never read:

https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/preprocessor/PpScanner.cpp#L182

Value stored to 'word' is never read:

https://github.com/KhronosGroup/glslang/blob/master/SPIRV/SPVRemapper.cpp#L457
https://github.com/KhronosGroup/glslang/blob/master/SPIRV/SPVRemapper.cpp#L469

Value stored to 'nextInst' during its initialization is never read:

https://github.com/KhronosGroup/glslang/blob/master/SPIRV/SPVRemapper.cpp#L469

And that is all :) I can provide a pull request for most of these if you want (the only part that's a bit more complex is the allocation/free stuff around ReadFileData / FreeFileData).

@johnkslang
Copy link
Member

Tear down in the standalone app has not been a priority (since it exits), but I understand it is better to have it run clean. (Of far greater concern would be issues within the exposed programmatic interface.) I see ReadFileData() is pretty ugly archaic code. I fixed most of these as I read through your note (don't agree yet with the "'token' is never read" one, and the fragOutHasLocation is possibly useful when the functionality is finished). If there are others remaining, feel free to submit a pull request. (Except for SPVRemapper, someone is looking at that.)

Note that the original purpose of maxSourceString was to test splitting tokens across multiple strings, which makes the ReadFileData() code appear overly complex.

Thanks.

@johnkslang
Copy link
Member

The SPVRemapper has addressed this now. I think the key issues have been addressed. Will leave open a bit longer for any addition related issues, and will then close (or floooh can close).

@floooh
Copy link
Contributor Author

floooh commented Jul 20, 2015

Just did a quick analyzer run, there are a couple of uncritical 'value stored to xxx is never read' left, and no new warnings, so I'm closing this ticket :)

@floooh floooh closed this as completed Jul 20, 2015
johnkslang pushed a commit that referenced this issue Sep 3, 2019
glebm added a commit to glebm/glslang that referenced this issue Jan 30, 2021
UBSAN rightly complains on `push_front`:

    glslang/MachineIndependent/localintermediate.h:100:8: runtime error: load of value 160, which is not a valid value for type 'bool'
    #0 in glslang::TCall::TCall(glslang::TCall&&) glslang/MachineIndependent/localintermediate.h:100
    KhronosGroup#1 in void __gnu_cxx::new_allocator<std::_List_node<glslang::TCall> >::construct<glslang::TCall, glslang::TCall>(glslang::TCall*, glslang::TCall&&) /usr/include/c++/10/ext/new_allocator.h:150
    KhronosGroup#2 in void std::allocator_traits<std::allocator<std::_List_node<glslang::TCall> > >::construct<glslang::TCall, glslang::TCall>(std::allocator<std::_List_node<glslang::TCall> >&, glslang::TCall*, glslang::TCall&&) /usr/include/c++/10/bits/alloc_traits.h:512
    KhronosGroup#3 in std::_List_node<glslang::TCall>* std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::_M_create_node<glslang::TCall>(glslang::TCall&&) (...)
    KhronosGroup#4 in void std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::_M_insert<glslang::TCall>(std::_List_iterator<glslang::TCall>, glslang::TCall&&) /usr/include/c++/10/bits/stl_list.h:1911
    KhronosGroup#5 in std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::push_front(glslang::TCall&&) /usr/include/c++/10/bits/stl_list.h:1167
    KhronosGroup#6 in glslang::TIntermediate::addToCallGraph(TInfoSink&, std::__cxx11::basic_string<char, std::char_traits<char>, glslang::pool_allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, glslang::pool_allocator<char> > const&) glslang/MachineIndependent/Intermediate.cpp:2860

What happens here:

1. TCall's bool fields are not initialized on construction.
2. `push_front` move the `TCall` passed into it.
3. The move constructor copies unitialized bool, which may have an
   out-of-range value.

What this fix does:

Calls `emplace_back` to ensure no copy/move constructor is called.

Fixes KhronosGroup#2222
Refs KhronosGroup#2112
glebm added a commit to glebm/glslang that referenced this issue Jan 30, 2021
UBSAN rightly complains on `push_front` here:

    glslang/MachineIndependent/localintermediate.h:100:8: runtime error: load of value 160, which is not a valid value for type 'bool'
    #0 in glslang::TCall::TCall(glslang::TCall&&) glslang/MachineIndependent/localintermediate.h:100
    KhronosGroup#1 in void __gnu_cxx::new_allocator<std::_List_node<glslang::TCall> >::construct<glslang::TCall, glslang::TCall>(glslang::TCall*, glslang::TCall&&) /usr/include/c++/10/ext/new_allocator.h:150
    KhronosGroup#2 in void std::allocator_traits<std::allocator<std::_List_node<glslang::TCall> > >::construct<glslang::TCall, glslang::TCall>(std::allocator<std::_List_node<glslang::TCall> >&, glslang::TCall*, glslang::TCall&&) /usr/include/c++/10/bits/alloc_traits.h:512
    KhronosGroup#3 in std::_List_node<glslang::TCall>* std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::_M_create_node<glslang::TCall>(glslang::TCall&&) (...)
    KhronosGroup#4 in void std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::_M_insert<glslang::TCall>(std::_List_iterator<glslang::TCall>, glslang::TCall&&) /usr/include/c++/10/bits/stl_list.h:1911
    KhronosGroup#5 in std::__cxx11::list<glslang::TCall, std::allocator<glslang::TCall> >::push_front(glslang::TCall&&) /usr/include/c++/10/bits/stl_list.h:1167
    KhronosGroup#6 in glslang::TIntermediate::addToCallGraph(TInfoSink&, std::__cxx11::basic_string<char, std::char_traits<char>, glslang::pool_allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, glslang::pool_allocator<char> > const&) glslang/MachineIndependent/Intermediate.cpp:2860

What happens here:

1. TCall's bool fields are not initialized on construction.
2. `push_front` move the `TCall` passed into it.
3. The move constructor copies unitialized bool, which may have an
   out-of-range value.

What this fix does:

Calls `emplace_back` to ensure no copy/move constructor is called.

Fixes KhronosGroup#2222
Refs KhronosGroup#2112
jsmall-zzz added a commit to jsmall-zzz/glslang that referenced this issue Nov 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants