mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
Merge branch '50-model-gettext-family-of-string-operations' into 51-2cppnon-constant-format-alter-not-const-source
This commit is contained in:
@@ -3,6 +3,7 @@ private import implementations.Deallocation
|
||||
private import implementations.Fread
|
||||
private import implementations.Getenv
|
||||
private import implementations.Gets
|
||||
private import implementations.GetText
|
||||
private import implementations.IdentityFunction
|
||||
private import implementations.Inet
|
||||
private import implementations.Iterator
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
|
||||
/**
|
||||
* Returns the transated text index for a given gettext function `f`
|
||||
*/
|
||||
private int getTextArg(Function f) {
|
||||
// basic variations of gettext
|
||||
f.hasGlobalOrStdName("gettext") and result = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("dgettext") and result = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("dcgettext") and result = 1
|
||||
or
|
||||
// plural variations of gettext that take one format string for singular and another for plural form
|
||||
f.hasGlobalOrStdName("ngettext") and
|
||||
(result = 0 or result = 1)
|
||||
or
|
||||
f.hasGlobalOrStdName("dngettext") and
|
||||
(result = 1 or result = 2)
|
||||
or
|
||||
f.hasGlobalOrStdName("dcngettext") and
|
||||
(result = 1 or result = 2)
|
||||
}
|
||||
|
||||
class GetTextFunction extends DataFlowFunction {
|
||||
int argInd;
|
||||
|
||||
GetTextFunction() { argInd = getTextArg(this) }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(argInd) and output.isReturnValueDeref()
|
||||
}
|
||||
}
|
||||
4
cpp/ql/src/change-notes/2024-02-05-gettext-dataflows.md
Normal file
4
cpp/ql/src/change-notes/2024-02-05-gettext-dataflows.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added dataflow models for the `gettext` function variants.
|
||||
@@ -936,4 +936,105 @@ namespace global_variable_conflation_test {
|
||||
sink(global_pointer); // clean
|
||||
sink(*global_pointer); // $ ir MISSING: ast
|
||||
}
|
||||
}
|
||||
|
||||
char* gettext(const char*);
|
||||
char* dgettext(const char*, const char*);
|
||||
char* ngettext(const char*, const char*, unsigned long int);
|
||||
char* dngettext (const char*, const char *, const char *, unsigned long int);
|
||||
|
||||
namespace test_gettext {
|
||||
char* source();
|
||||
char* indirect_source();
|
||||
|
||||
void test_gettext() {
|
||||
char* data = source();
|
||||
char* translated = gettext(data);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
}
|
||||
|
||||
void indirect_test_dgettext() {
|
||||
char* data = indirect_source();
|
||||
char* translated = gettext(data);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_dgettext() {
|
||||
char* data = source();
|
||||
char* domain = source(); // Should not trace from this source
|
||||
char* translated = dgettext(domain, data);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
}
|
||||
|
||||
void indirect_test_gettext() {
|
||||
char* data = indirect_source();
|
||||
char* domain = indirect_source(); // Should not trace from this source
|
||||
char* translated = dgettext(domain, data);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_ngettext() {
|
||||
char* data = source();
|
||||
char* np = nullptr; // Don't coun't as a source
|
||||
|
||||
char* translated = ngettext(data, np, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
|
||||
translated = ngettext(np, data, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
}
|
||||
|
||||
void indirect_test_ngettext() {
|
||||
char* data = indirect_source();
|
||||
char* np = nullptr; // Don't coun't as a source
|
||||
|
||||
char* translated = ngettext(data, np, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
|
||||
translated = ngettext(np, data, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_dngettext() {
|
||||
char* data = source();
|
||||
char* np = nullptr; // Don't coun't as a source
|
||||
char* domain = source(); // Should not trace from this source
|
||||
|
||||
char* translated = dngettext(domain, data, np, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
|
||||
translated = dngettext(domain, np, data, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
}
|
||||
|
||||
void indirect_test_dngettext() {
|
||||
char* data = indirect_source();
|
||||
char* np = nullptr; // Don't coun't as a source
|
||||
char* domain = indirect_source(); // Should not trace from this source
|
||||
|
||||
char* translated = dngettext(domain, data, np, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
|
||||
translated = dngettext(domain, np, data, 0);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void indirect_test_gettext_no_flow_from_domain() {
|
||||
char* domain = source(); // Should not trace from this source
|
||||
char* translated = dgettext(domain, nullptr);
|
||||
sink(translated); // clean
|
||||
indirect_sink(translated); // clean
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user