diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9c7d0cf --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,27 @@ +name: 🧪 build + +on: + push: + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Get deps + run: | + sudo apt-get install cmake ninja-build clang + + - name: Build + run: | + mkdir -p build + cd build + cmake -GNinja .. + ninja + diff --git a/.github/workflows/clang_static_analyzer.yml b/.github/workflows/clang_static_analyzer.yml new file mode 100644 index 0000000..4ed03df --- /dev/null +++ b/.github/workflows/clang_static_analyzer.yml @@ -0,0 +1,15 @@ +name: CLang Static Analyzer + +on: [push, pull_request] + +jobs: + + clang_static_analyzer: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Run + run: .github/workflows/clang_static_analyzer/start.sh diff --git a/.github/workflows/clang_static_analyzer/start.sh b/.github/workflows/clang_static_analyzer/start.sh new file mode 100755 index 0000000..33419b9 --- /dev/null +++ b/.github/workflows/clang_static_analyzer/start.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -e + +sudo apt update + +DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends \ + libtool g++ make jq clang-tools + +# prepare build files +mkdir -p build +cd build + +NPROC=$(nproc) +echo "NPROC=${NPROC}" +export MAKEFLAGS="-j ${NPROC}" + +CXXFLAGS="-std=c++11" scan-build -o scanbuildoutput -plist -v cmake .. +rm -rf scanbuildoutput +TOPDIR=$PWD +scan-build -o $TOPDIR/scanbuildoutput -sarif -v -enable-checker alpha.unix.cstring.OutOfBounds,alpha.unix.cstring.BufferOverlap,optin.cplusplus.VirtualCall,optin.cplusplus.UninitializedObject make + +rm -f filtered_scanbuild.txt +files=$(find scanbuildoutput -name "*.sarif") +for f in $files; do + jq '.runs[].results[] | (if .locations[].physicalLocation.fileLocation.uri | (contains("_generated_parser") ) then empty else { "uri": .locations[].physicalLocation.fileLocation.uri, "msg": .message.text, "location": .codeFlows[-1].threadFlows[-1].locations[-1] } end)' < $f > tmp.txt + if [ -s tmp.txt ]; then + echo "Errors from $f: " + cat $f + echo "" + cat tmp.txt >> filtered_scanbuild.txt + fi +done +if [ -s filtered_scanbuild.txt ]; then + echo "" + echo "" + echo "========================" + echo "Summary of errors found:" + cat filtered_scanbuild.txt + /bin/false +fi diff --git a/.github/workflows/code_checks.yml b/.github/workflows/code_checks.yml new file mode 100644 index 0000000..3cebab2 --- /dev/null +++ b/.github/workflows/code_checks.yml @@ -0,0 +1,39 @@ +name: Code Checks + +on: + push: + pull_request: + branches: + - master + +jobs: + + cppcheck_2004: + runs-on: ubuntu-20.04 + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Requirements + run: | + sudo apt update + sudo apt install -y cppcheck + + - name: Run cppcheck test + run: ./scripts/cppcheck.sh + + cppcheck_latest: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Requirements + run: | + sudo apt update + sudo apt install -y cppcheck + + - name: Run cppcheck test + run: ./scripts/cppcheck.sh diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 0000000..96d76f8 --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,42 @@ +name: MacOS build + +on: + push: + pull_request: + branches: + - master + +jobs: + macos_build: + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: conda-incubator/setup-miniconda@v2 + with: + channels: conda-forge + auto-update-conda: true + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: ~/.ccache + key: ${{ runner.os }}-cache-mac-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-mac- + + - name: Install Requirements + shell: bash -l {0} + run: | + source .github/workflows/mac/before_install.sh + + - name: Build + shell: bash -l {0} + run: | + source .github/workflows/mac/install.sh + env: + TRAVIS_OS_NAME: osx + BUILD_NAME: osx + diff --git a/.github/workflows/mac/before_install.sh b/.github/workflows/mac/before_install.sh new file mode 100644 index 0000000..369e732 --- /dev/null +++ b/.github/workflows/mac/before_install.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + + +conda update -n base -c defaults conda +conda install compilers -y + +conda config --set channel_priority strict +conda install --yes --quiet libtool ccache ninja -y + diff --git a/.github/workflows/mac/install.sh b/.github/workflows/mac/install.sh new file mode 100644 index 0000000..87edbf9 --- /dev/null +++ b/.github/workflows/mac/install.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +export CCACHE_CPP2=yes +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +ccache -M 200M +ccache -s + +export CC="ccache clang" +export CXX="ccache clang++" +export CFLAGS="-Werror -O2" +export CXXFLAGS="-Werror -O2" + +mkdir -p build +cd build +cmake -GNinja .. +ninja + +ccache -s diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 94a50e8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: cpp - -matrix: - include: - - os: linux - dist: trusty - sudo: false - compiler: gcc - -cache: ccache - - -script: - - mkdir -p build - - cd build - - cmake .. - - make -j2 \ No newline at end of file diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh new file mode 100755 index 0000000..7f2f33c --- /dev/null +++ b/scripts/cppcheck.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +set -eu + +SCRIPT_DIR=$(dirname "$0") +case $SCRIPT_DIR in + "/"*) + ;; + ".") + SCRIPT_DIR=$(pwd) + ;; + *) + SCRIPT_DIR=$(pwd)/$(dirname "$0") + ;; +esac + +LOG_FILE=/tmp/cppcheck_libdxfrw.txt + +rm -f ${LOG_FILE} +echo "Checking ${SCRIPT_DIR}/../src ..." + +cppcheck --inline-suppr \ + --template='{file}:{line},{severity},{id},{message}' \ + --enable=all --inconclusive --std=c++11 \ + -j $(nproc) \ + ${SCRIPT_DIR}/../src \ + >>${LOG_FILE} 2>&1 & + +PID=$! +while kill -0 $PID 2>/dev/null; do + printf "." + sleep 1 +done +echo " done" +if ! wait $PID; then + echo "cppcheck failed" + exit 1 +fi + +ret_code=0 + +cat ${LOG_FILE} | grep -v -e "syntaxError," -e "cppcheckError," > ${LOG_FILE}.tmp +mv ${LOG_FILE}.tmp ${LOG_FILE} + +for category in "style" "performance" "portability" "warning"; do + if grep "${category}," ${LOG_FILE} >/dev/null; then + echo "INFO: Issues in '${category}' category found, but not considered as making script to fail:" + grep "${category}," ${LOG_FILE} | grep -v -e "clarifyCalculation," -e "duplicateExpressionTernary," -e "redundantCondition," -e "unusedPrivateFunction," -e "postfixOperator," + echo "" + fi +done + +# unusedPrivateFunction not reliable enough in cppcheck 1.72 of Ubuntu 16.04 +if test "$(cppcheck --version)" = "Cppcheck 1.72"; then + UNUSED_PRIVATE_FUNCTION="" +else + UNUSED_PRIVATE_FUNCTION="unusedPrivateFunction" +fi + +for category in "error" "clarifyCalculation" "duplicateExpressionTernary" "redundantCondition" "postfixOperator" "${UNUSED_PRIVATE_FUNCTION}"; do + if test "${category}" != ""; then + if grep "${category}," ${LOG_FILE} >/dev/null; then + echo "ERROR: Issues in '${category}' category found:" + grep "${category}," ${LOG_FILE} + echo "" + echo "${category} check failed !" + ret_code=1 + fi + fi +done + +if [ ${ret_code} = 0 ]; then + echo "cppcheck succeeded" +fi + +exit ${ret_code} diff --git a/src/drw_header.cpp b/src/drw_header.cpp index 0081725..8b8d65f 100644 --- a/src/drw_header.cpp +++ b/src/drw_header.cpp @@ -2400,9 +2400,8 @@ bool DRW_Header::parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *hBbuf } //temporary code to show header end sentinel - duint64 sz= buf->size()-1; if (version < DRW::AC1018) {//pre 2004 - sz= buf->size()-16; + const duint64 sz= buf->size()-16; buf->setPosition(sz); DRW_DBG("\nseting position to: "); DRW_DBG(buf->getPosition()); DRW_DBG("\ndwg header end sentinel= "); @@ -2419,7 +2418,7 @@ bool DRW_Header::parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *hBbuf DRW_DBGH(buf->getRawChar8()); DRW_DBG(" "); } } else if (version == DRW::AC1021) {//2007 - sz= buf->size()-16; + const duint64 sz= buf->size()-16; buf->setPosition(sz); DRW_DBG("\nseting position to: "); DRW_DBG(buf->getPosition()); DRW_DBG("\ndwg header end sentinel= "); diff --git a/src/intern/dwgreader.cpp b/src/intern/dwgreader.cpp index 05aa819..73c0e9c 100644 --- a/src/intern/dwgreader.cpp +++ b/src/intern/dwgreader.cpp @@ -710,6 +710,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { ret = false; } else { //reset position buff.resetPosition(); + (void)bs; /* RLZ: writeme ret2 = vpEntHeader.parseDwg(version, &buff, bs); if(ret) ret = ret2;*/ diff --git a/src/intern/dwgreader.h b/src/intern/dwgreader.h index 91aebc9..2d62b6f 100644 --- a/src/intern/dwgreader.h +++ b/src/intern/dwgreader.h @@ -60,13 +60,13 @@ class dwgPageInfo { dwgPageInfo(duint64 i, duint64 ad, duint32 sz){ Id=i; address=ad; size=sz; } - duint64 Id; - duint64 address; //in file stream, for rd18, rd21 - duint64 size; //in file stream, for rd18, rd21 - duint64 dataSize; //for rd18, rd21 - duint32 startOffset; //for rd18, rd21 - duint64 cSize; //compresed page size, for rd21 - duint64 uSize; //uncompresed page size, for rd21 + duint64 Id{0}; + duint64 address{0}; //in file stream, for rd18, rd21 + duint64 size{0}; //in file stream, for rd18, rd21 + duint64 dataSize{0}; //for rd18, rd21 + duint32 startOffset{0}; //for rd18, rd21 + duint64 cSize{0}; //compressed page size, for rd21 + duint64 uSize{0}; //uncompressed page size, for rd21 }; // sections of file diff --git a/src/intern/dwgreader18.cpp b/src/intern/dwgreader18.cpp index e55c8a0..858bbe7 100644 --- a/src/intern/dwgreader18.cpp +++ b/src/intern/dwgreader18.cpp @@ -21,6 +21,7 @@ #include "drw_textcodec.h" #include "../libdwgr.h" +#if 0 void dwgReader18::genMagicNumber(){ int size =0x114; duint8 *tmpMagicStr = new duint8[size]; @@ -45,6 +46,7 @@ void dwgReader18::genMagicNumber(){ } delete[]tmpMagicStr; } +#endif duint32 dwgReader18::checksum(duint32 seed, duint8* data, duint32 sz){ duint32 size = sz; @@ -208,7 +210,9 @@ bool dwgReader18::readFileHeader() { if (! fileBuf->setPosition(0x80)) return false; -// genMagicNumber(); DBG("\n"); DBG("\n"); +#if 0 + genMagicNumber(); DBG("\n"); DBG("\n"); +#endif DRW_DBG("Encripted Header Data=\n"); duint8 byteStr[0x6C]; int size =0x6C; diff --git a/src/intern/dwgreader18.h b/src/intern/dwgreader18.h index 50ab674..fb6dc43 100644 --- a/src/intern/dwgreader18.h +++ b/src/intern/dwgreader18.h @@ -81,7 +81,10 @@ class dwgReader18 : public dwgReader { duint64 uncompSize; private: +#if 0 void genMagicNumber(); +#endif + // dwgBuffer* bufObj; void parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b bool parseDataPage(const dwgSectionInfo &si/*, duint8 *dData*/); //called ???: Section map: 0x4163003b diff --git a/src/intern/dwgreader21.cpp b/src/intern/dwgreader21.cpp index 6d8af23..bf6ff6a 100644 --- a/src/intern/dwgreader21.cpp +++ b/src/intern/dwgreader21.cpp @@ -260,8 +260,10 @@ bool dwgReader21::readFileHeader() { duint8 *SectionsMapData = new duint8[SectionsMapSizeUncompressed]; dwgPageInfo sectionMap = sectionPageMapTmp[SectionsMapId]; ret = parseSysPage(SectionsMapSizeCompressed, SectionsMapSizeUncompressed, SectionsMapCorrectionFactor, sectionMap.address, SectionsMapData); - if (!ret) + if (!ret) { + delete[]SectionsMapData; return false; + } //reads sections: //Note: compressed value are not stored in file then, commpresed field are use to store