From a5f36aa46c2fe257841cf9daa1f031f5e7ed0687 Mon Sep 17 00:00:00 2001 From: tosttost Date: Sun, 21 Feb 2021 17:32:08 +0100 Subject: [PATCH] fix undefined behavour due to memcpy(ptr, NULL, 0) --- src/CglCommon/CglTreeInfo.cpp | 53 +++++++---------------------- src/CglCommon/CglTreeInfo.hpp | 14 ++++++++ src/CglPreProcess/CglPreProcess.cpp | 9 +++-- 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/src/CglCommon/CglTreeInfo.cpp b/src/CglCommon/CglTreeInfo.cpp index 7dc5fdd2..9cdb170f 100644 --- a/src/CglCommon/CglTreeInfo.cpp +++ b/src/CglCommon/CglTreeInfo.cpp @@ -1013,25 +1013,13 @@ CglTreeProbingInfo::analyze(const OsiSolverInterface &si, int createSolver, nStrengthen++; if (numberEntries + jCount + 1 > maximumEntries) { maximumEntries = CoinMax(numberEntries + jCount + 1, (maximumEntries * 12) / 10 + 100); - CliqueEntry *temp = new CliqueEntry[maximumEntries]; - memcpy(temp, entry, numberEntries * sizeof(CliqueEntry)); - delete[] entry; - entry = temp; - int *tempI = new int[maximumEntries]; - memcpy(tempI, whichClique, numberEntries * sizeof(int)); - delete[] whichClique; - whichClique = tempI; + append(entry, numberEntries, maximumEntries); + append(whichClique, numberEntries, maximumEntries); } if (numberCliques == maximumCliques) { maximumCliques = (maximumCliques * 12) / 10 + 100; - CoinBigIndex *temp = new CoinBigIndex[maximumCliques + 1]; - memcpy(temp, cliqueStart, (numberCliques + 1) * sizeof(CoinBigIndex)); - delete[] cliqueStart; - cliqueStart = temp; - char *tempT = new char[maximumCliques]; - memcpy(tempT, cliqueType, numberCliques); - delete[] cliqueType; - cliqueType = tempT; + append(cliqueStart, numberCliques + 1, maximumCliques + 1); + append(cliqueType, numberCliques, maximumCliques); } CliqueEntry eI; eI.fixes = 0; @@ -1102,25 +1090,14 @@ CglTreeProbingInfo::analyze(const OsiSolverInterface &si, int createSolver, nStrengthen++; if (numberEntries + jCount + 1 > maximumEntries) { maximumEntries = CoinMax(numberEntries + jCount + 1, (maximumEntries * 12) / 10 + 100); - CliqueEntry *temp = new CliqueEntry[maximumEntries]; - memcpy(temp, entry, numberEntries * sizeof(CliqueEntry)); - delete[] entry; - entry = temp; - int *tempI = new int[maximumEntries]; - memcpy(tempI, whichClique, numberEntries * sizeof(int)); - delete[] whichClique; - whichClique = tempI; + append(entry, numberEntries, maximumEntries); + append(whichClique, numberEntries, maximumEntries); } if (numberCliques == maximumCliques) { maximumCliques = (maximumCliques * 12) / 10 + 100; - CoinBigIndex *temp = new CoinBigIndex[maximumCliques + 1]; - memcpy(temp, cliqueStart, (numberCliques + 1) * sizeof(CoinBigIndex)); - delete[] cliqueStart; - cliqueStart = temp; - char *tempT = new char[maximumCliques]; - memcpy(tempT, cliqueType, numberCliques); - delete[] cliqueType; - cliqueType = tempT; + + append(cliqueStart, numberCliques + 1, maximumCliques + 1); + append(cliqueType, numberCliques, maximumCliques); } CliqueEntry eI; eI.fixes = 0; @@ -1232,6 +1209,7 @@ CglTreeProbingInfo::analyze(const OsiSolverInterface &si, int createSolver, delete[] whichClique; return newSolver; } + // Take action if cut generator can fix a variable (toValue -1 for down, +1 for up) bool CglTreeProbingInfo::fixes(int variable, int toValue, int fixedVariable, bool fixedToLower) { @@ -1248,14 +1226,9 @@ bool CglTreeProbingInfo::fixes(int variable, int toValue, int fixedVariable, boo if (maximumEntries_ >= CoinMax(1000000, 10 * numberIntegers_)) return false; maximumEntries_ += 100 + maximumEntries_ / 2; - CliqueEntry *temp1 = new CliqueEntry[maximumEntries_]; - memcpy(temp1, fixEntry_, numberEntries_ * sizeof(CliqueEntry)); - delete[] fixEntry_; - fixEntry_ = temp1; - int *temp2 = new int[maximumEntries_]; - memcpy(temp2, fixingEntry_, numberEntries_ * sizeof(int)); - delete[] fixingEntry_; - fixingEntry_ = temp2; + + append(fixEntry_, numberEntries_, maximumEntries_); + append(fixingEntry_, numberEntries_, maximumEntries_); } CliqueEntry entry1; entry1.fixes = 0; diff --git a/src/CglCommon/CglTreeInfo.hpp b/src/CglCommon/CglTreeInfo.hpp index 26baac13..20fd11db 100644 --- a/src/CglCommon/CglTreeInfo.hpp +++ b/src/CglCommon/CglTreeInfo.hpp @@ -10,6 +10,20 @@ #include "CoinHelperFunctions.hpp" #include "CglConfig.h" +template +void append(T*& array, int oldLength, int newLength) +{ + assert(oldLength < newLength); + + T* temp = new T[newLength]; + if (array != NULL) { + memcpy(temp, array, oldLength * sizeof(T)); + delete[] array; + } + + array = temp; +} + class CglStored; /** Information about where the cut generator is invoked from. */ diff --git a/src/CglPreProcess/CglPreProcess.cpp b/src/CglPreProcess/CglPreProcess.cpp index 28589f89..5427cac7 100644 --- a/src/CglPreProcess/CglPreProcess.cpp +++ b/src/CglPreProcess/CglPreProcess.cpp @@ -2797,7 +2797,9 @@ CglPreProcess::preProcessNonDefault(OsiSolverInterface &model, int nAdd = ((tuning & (64 + USECGLCLIQUE)) == 64 + USECGLCLIQUE && allPlusOnes) ? 2 : 1; CglCutGenerator **temp = generator_; generator_ = new CglCutGenerator *[numberCutGenerators_ + nAdd]; - memcpy(generator_ + nAdd, temp, numberCutGenerators_ * sizeof(CglCutGenerator *)); + if(temp != NULL) { + memcpy(generator_ + nAdd, temp, numberCutGenerators_ * sizeof(CglCutGenerator *)); + } delete[] temp; numberCutGenerators_ += nAdd; if (nAdd == 2 || (tuning & USECGLCLIQUE) != 0) { @@ -7938,10 +7940,7 @@ void CglPreProcess::gutsOfDestructor() // Add one generator void CglPreProcess::addCutGenerator(CglCutGenerator *generator) { - CglCutGenerator **temp = generator_; - generator_ = new CglCutGenerator *[numberCutGenerators_ + 1]; - memcpy(generator_, temp, numberCutGenerators_ * sizeof(CglCutGenerator *)); - delete[] temp; + append(generator_, numberCutGenerators_, numberCutGenerators_ + 1); generator_[numberCutGenerators_++] = generator->clone(); } //#############################################################################