diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4ae52284f8a..bf610a684bf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -74,9 +74,15 @@ jobs: - name: Install C++ build deps if: matrix.language == 'c-cpp' + # bison + flex are needed to regenerate xml.cc / slghparse.cc / + # slghscan.cc from their .y / .l sources during the manual + # build below. The decompiler's actual link step (decomp_dbg) + # would want binutils-dev + libiberty-dev for BFD, but we don't + # link here — only compile to .o files for CodeQL to extract, + # which doesn't need BFD. run: | sudo apt-get update - sudo apt-get install -y bison flex g++ make binutils-dev libiberty-dev + sudo apt-get install -y bison flex g++ make - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -97,8 +103,23 @@ jobs: # irrelevant to static analysis. run: gradle prepDev --parallel - - name: Autobuild (non-Java) - if: matrix.language != 'java-kotlin' + - name: Manual C++ build + if: matrix.language == 'c-cpp' + # Autobuild fails for this repo because the decompiler's + # Makefile lives at Ghidra/Features/Decompiler/src/decompile/cpp/ + # rather than at the repo root, so `cpp/autobuilder.sh` reports + # "No supported build system detected" and exits 1. Build the + # static library `libdecomp_dbg.a` instead — that target + # compiles every C++ source file in the decompiler core (all + # LIBDECOMP_NAMES → com_dbg/*.o, then ar qc into the archive) + # without needing BFD at link time. CodeQL's tracer picks up + # the .o compile commands, which is what static analysis needs. + run: | + cd Ghidra/Features/Decompiler/src/decompile/cpp + make libdecomp_dbg.a + + - name: Autobuild (other languages) + if: matrix.language != 'java-kotlin' && matrix.language != 'c-cpp' uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.cc index 6831da5a65c..13bf3ccf233 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.cc @@ -127,7 +127,7 @@ class XmlScan { private: mode curmode; ///< The current scanning mode istream &s; ///< The stream being scanned - string *lvalue; ///< Current string being built + unique_ptr lvalue; ///< Current string being built; nullptr when no token in progress int4 lookahead[4]; ///< Lookahead into the byte stream int4 pos; ///< Current position in the lookahead buffer bool endofstream; ///< Has end of stream been reached @@ -173,7 +173,7 @@ class XmlScan { ~XmlScan(void); ///< Destructor void setmode(mode m) { curmode = m; } ///< Set the scanning mode int4 nexttoken(void); ///< Get the next token - string *lval(void) { string *ret = lvalue; lvalue = (string *)0; return ret; } ///< Return the last \e lvalue string + string *lval(void) { return lvalue.release(); } ///< Transfer ownership of the last \e lvalue string to the caller (typically yylval on the bison value stack); leaves lvalue null. Caller deletes. }; /// \brief A parsed name/value pair @@ -2081,7 +2081,7 @@ XmlScan::XmlScan(istream &t) : s(t) { curmode = SingleMode; - lvalue = (string *)0; + // lvalue (unique_ptr) default-constructs to nullptr; no explicit init needed. pos = 0; endofstream = false; getxmlchar(); getxmlchar(); getxmlchar(); getxmlchar(); // Fill lookahead buffer @@ -2096,8 +2096,7 @@ XmlScan::~XmlScan(void) void XmlScan::clearlvalue(void) { - if (lvalue != (string *)0) - delete lvalue; + lvalue.reset(); } int4 XmlScan::scanSingle(void) @@ -2115,7 +2114,7 @@ int4 XmlScan::scanCharData(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { // look for '<' '&' or ']]>' if (next(0) == '<') break; @@ -2135,7 +2134,7 @@ int4 XmlScan::scanCData(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { // Look for "]]>" and non-Char if (next(0)==']') @@ -2153,7 +2152,7 @@ int4 XmlScan::scanCharRef(void) { int4 v; clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (next(0) == 'x') { *lvalue += getxmlchar(); while(next(0) != -1) { @@ -2184,7 +2183,7 @@ int4 XmlScan::scanAttValue(int4 quote) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { if (next(0) == quote) break; if (next(0) == '<') break; @@ -2200,7 +2199,7 @@ int4 XmlScan::scanComment(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { if (next(0)=='-') @@ -2216,7 +2215,7 @@ int4 XmlScan::scanName(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (!isInitialNameChar(next(0))) return scanSingle(); @@ -2237,7 +2236,7 @@ int4 XmlScan::scanSName(void) getxmlchar(); } clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (!isInitialNameChar(next(0))) { // First non-whitespace is not Name char if (whitecount > 0) return ' '; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.hh index 72533012a13..78f7bfe52fd 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.hh @@ -21,13 +21,17 @@ #include "types.h" #include #include +#include #include #include #include namespace ghidra { +using std::make_unique; +using std::move; using std::string; +using std::unique_ptr; using std::vector; using std::map; using std::istream; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.y b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.y index 222e9d495ec..f50093b8c31 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/xml.y +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/xml.y @@ -54,7 +54,7 @@ public: private: mode curmode; ///< The current scanning mode istream &s; ///< The stream being scanned - string *lvalue; ///< Current string being built + unique_ptr lvalue; ///< Current string being built; nullptr when no token in progress int4 lookahead[4]; ///< Lookahead into the byte stream int4 pos; ///< Current position in the lookahead buffer bool endofstream; ///< Has end of stream been reached @@ -100,7 +100,7 @@ public: ~XmlScan(void); ///< Destructor void setmode(mode m) { curmode = m; } ///< Set the scanning mode int4 nexttoken(void); ///< Get the next token - string *lval(void) { string *ret = lvalue; lvalue = (string *)0; return ret; } ///< Return the last \e lvalue string + string *lval(void) { return lvalue.release(); } ///< Transfer ownership of the last \e lvalue string to the caller (typically yylval on the bison value stack); leaves lvalue null. Caller deletes. }; /// \brief A parsed name/value pair @@ -223,7 +223,7 @@ XmlScan::XmlScan(istream &t) : s(t) { curmode = SingleMode; - lvalue = (string *)0; + // lvalue (unique_ptr) default-constructs to nullptr; no explicit init needed. pos = 0; endofstream = false; getxmlchar(); getxmlchar(); getxmlchar(); getxmlchar(); // Fill lookahead buffer @@ -238,8 +238,7 @@ XmlScan::~XmlScan(void) void XmlScan::clearlvalue(void) { - if (lvalue != (string *)0) - delete lvalue; + lvalue.reset(); } int4 XmlScan::scanSingle(void) @@ -257,7 +256,7 @@ int4 XmlScan::scanCharData(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { // look for '<' '&' or ']]>' if (next(0) == '<') break; @@ -277,7 +276,7 @@ int4 XmlScan::scanCData(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { // Look for "]]>" and non-Char if (next(0)==']') @@ -295,7 +294,7 @@ int4 XmlScan::scanCharRef(void) { int4 v; clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (next(0) == 'x') { *lvalue += getxmlchar(); while(next(0) != -1) { @@ -326,7 +325,7 @@ int4 XmlScan::scanAttValue(int4 quote) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { if (next(0) == quote) break; if (next(0) == '<') break; @@ -342,7 +341,7 @@ int4 XmlScan::scanComment(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); while(next(0) != -1) { if (next(0)=='-') @@ -358,7 +357,7 @@ int4 XmlScan::scanName(void) { clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (!isInitialNameChar(next(0))) return scanSingle(); @@ -379,7 +378,7 @@ int4 XmlScan::scanSName(void) getxmlchar(); } clearlvalue(); - lvalue = new string(); + lvalue = make_unique(); if (!isInitialNameChar(next(0))) { // First non-whitespace is not Name char if (whitecount > 0) return ' ';