diff --git a/CHANGELOG b/CHANGELOG index 7b8d21161..4b11535b1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -38,7 +38,7 @@ Release 1.5.4 (2014-10-13) - HTTPCookie: fix documentation for max age - added Timestamp::raw() and Clock::raw() - Poco::Buffer properly handles zero-sized buffers - +- GH #512: Poco:Data:ODBC:Binder.h causes a crash Release 1.5.3 (2014-06-30) ========================== diff --git a/Data/ODBC/include/Poco/Data/ODBC/Binder.h b/Data/ODBC/include/Poco/Data/ODBC/Binder.h index f7e6a303b..a34317011 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Binder.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Binder.h @@ -353,15 +353,20 @@ public: /// Clears the cached storage. private: - typedef std::vector LengthVec; - typedef std::vector > LengthVecVec; + typedef std::vector LengthPtrVec; + typedef std::vector LengthVec; + typedef std::vector LengthVecVec; typedef std::vector CharPtrVec; typedef std::vector UTF16CharPtrVec; typedef std::vector BoolPtrVec; - typedef std::vector > DateVec; - typedef std::vector > TimeVec; - typedef std::vector > DateTimeVec; - typedef std::vector > AnyVec; + typedef std::vector DateVec; + typedef std::vector DateVecVec; + typedef std::vector TimeVec; + typedef std::vector TimeVecVec; + typedef std::vector DateTimeVec; + typedef std::vector DateTimeVecVec; + typedef std::vector AnyVec; + typedef std::vector AnyVecVec; typedef std::map StringMap; typedef std::map UTF16StringMap; typedef std::map DateMap; @@ -450,8 +455,8 @@ private: if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(length, sizeof(T)); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length); } if (Utility::isError(SQLBindParameter(_rStmt, @@ -463,7 +468,7 @@ private: decDigits, (SQLPOINTER) &val[0], 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter()"); } @@ -502,8 +507,8 @@ private: if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(length, sizeof(bool)); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length); } if (_boolPtrs.size() <= pos) @@ -524,7 +529,7 @@ private: decDigits, (SQLPOINTER) &_boolPtrs[pos][0], 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter()"); } @@ -540,10 +545,12 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Containers can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + + if (0 == length) throw InvalidArgumentException("Empty container not allowed."); - setParamSetSize(val.size()); + setParamSetSize(length); SQLINTEGER size = 0; getColumnOrParameterSize(pos, size); @@ -558,8 +565,8 @@ private: if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), SQL_NTS); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS); } if (_charPtrs.size() <= pos) @@ -589,7 +596,7 @@ private: 0, _charPtrs[pos], (SQLINTEGER) size, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(std::vector)"); } @@ -605,7 +612,8 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Containers can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + if (0 == length) throw InvalidArgumentException("Empty container not allowed."); setParamSetSize(val.size()); @@ -623,8 +631,8 @@ private: if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), SQL_NTS); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS); } if (_utf16CharPtrs.size() <= pos) @@ -654,7 +662,7 @@ private: 0, _utf16CharPtrs[pos], (SQLINTEGER)size, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(std::vector)"); } @@ -672,19 +680,22 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Containers can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + if (0 == length) throw InvalidArgumentException("Empty container not allowed."); - setParamSetSize(val.size()); + setParamSetSize(length); SQLINTEGER size = 0; if (_vecLengthIndicator.size() <= pos) - _vecLengthIndicator.resize(pos + 1); - - _vecLengthIndicator[pos].resize(val.size()); - std::vector::iterator lIt = _vecLengthIndicator[pos].begin(); - std::vector::iterator lEnd = _vecLengthIndicator[pos].end(); + { + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1); + } + + std::vector::iterator lIt = _vecLengthIndicator[pos]->begin(); + std::vector::iterator lEnd = _vecLengthIndicator[pos]->end(); typename C::const_iterator cIt = val.begin(); for (; lIt != lEnd; ++lIt, ++cIt) { @@ -721,7 +732,7 @@ private: 0, _charPtrs[pos], (SQLINTEGER) size, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(std::vector)"); } @@ -736,21 +747,28 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("std::vector can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + + if (0 == length) throw InvalidArgumentException("Empty vector not allowed."); - setParamSetSize(val.size()); + setParamSetSize(length); SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT); if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), size); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1); } - if (_dateVec.size() <= pos) _dateVec.resize(pos + 1); - Utility::dateSync(_dateVec[pos], val); + if (_dateVecVec.size() <= pos) + { + _dateVecVec.resize(pos + 1, 0); + _dateVecVec[pos] = new DateVec(length ? length : 1); + } + + Utility::dateSync(*_dateVecVec[pos], val); SQLINTEGER colSize = 0; SQLSMALLINT decDigits = 0; @@ -763,9 +781,9 @@ private: SQL_TYPE_DATE, colSize, decDigits, - (SQLPOINTER) &_dateVec[pos][0], + (SQLPOINTER) &(*_dateVecVec[pos])[0], 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(Date[])"); } @@ -780,7 +798,8 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Containers can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + if (0 == length) throw InvalidArgumentException("Empty container not allowed."); setParamSetSize(val.size()); @@ -789,12 +808,17 @@ private: if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), size); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1); } - if (_timeVec.size() <= pos) _timeVec.resize(pos + 1); - Utility::timeSync(_timeVec[pos], val); + if (_timeVecVec.size() <= pos) + { + _timeVecVec.resize(pos + 1, 0); + _timeVecVec[pos] = new TimeVec(length ? length : 1); + } + + Utility::timeSync(*_timeVecVec[pos], val); SQLINTEGER colSize = 0; SQLSMALLINT decDigits = 0; @@ -807,9 +831,9 @@ private: SQL_TYPE_TIME, colSize, decDigits, - (SQLPOINTER) &_timeVec[pos][0], + (SQLPOINTER) &(*_timeVecVec[pos])[0], 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(Time[])"); } @@ -824,21 +848,28 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Containers can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + + if (0 == length) throw InvalidArgumentException("Empty Containers not allowed."); - setParamSetSize(val.size()); + setParamSetSize(length); SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT); if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), size); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1); } - if (_dateTimeVec.size() <= pos) _dateTimeVec.resize(pos + 1); - Utility::dateTimeSync(_dateTimeVec[pos], val); + if (_dateTimeVecVec.size() <= pos) + { + _dateTimeVecVec.resize(pos + 1, 0); + _dateTimeVecVec[pos] = new DateTimeVec(length ? length : 1); + } + + Utility::dateTimeSync(*_dateTimeVecVec[pos], val); SQLINTEGER colSize = 0; SQLSMALLINT decDigits = 0; @@ -851,9 +882,9 @@ private: SQL_TYPE_TIMESTAMP, colSize, decDigits, - (SQLPOINTER) &_dateTimeVec[pos][0], + (SQLPOINTER) &(*_dateTimeVecVec[pos])[0], 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter(Time[])"); } @@ -868,17 +899,19 @@ private: if (PB_IMMEDIATE != _paramBinding) throw InvalidAccessException("Container can only be bound immediately."); - if (0 == val.size()) + std::size_t length = val.size(); + + if (0 == length) throw InvalidArgumentException("Empty container not allowed."); - setParamSetSize(val.size()); + setParamSetSize(length); SQLINTEGER size = SQL_NULL_DATA; if (_vecLengthIndicator.size() <= pos) { - _vecLengthIndicator.resize(pos + 1); - _vecLengthIndicator[pos].resize(val.size(), size); + _vecLengthIndicator.resize(pos + 1, 0); + _vecLengthIndicator[pos] = new LengthVec(length ? length : 1); } SQLINTEGER colSize = 0; @@ -894,7 +927,7 @@ private: decDigits, 0, 0, - &_vecLengthIndicator[pos][0]))) + &(*_vecLengthIndicator[pos])[0]))) { throw StatementException(_rStmt, "SQLBindParameter()"); } @@ -956,7 +989,7 @@ private: const StatementHandle& _rStmt; - LengthVec _lengthIndicator; + LengthPtrVec _lengthIndicator; LengthVecVec _vecLengthIndicator; ParamMap _inParams; @@ -969,16 +1002,16 @@ private: StringMap _strings; UTF16StringMap _utf16Strings; - DateVec _dateVec; - TimeVec _timeVec; - DateTimeVec _dateTimeVec; + DateVecVec _dateVecVec; + TimeVecVec _timeVecVec; + DateTimeVecVec _dateTimeVecVec; CharPtrVec _charPtrs; UTF16CharPtrVec _utf16CharPtrs; BoolPtrVec _boolPtrs; const TypeInfo* _pTypeInfo; SQLINTEGER _paramSetSize; std::size_t _maxFieldSize; - AnyVec _containers; + AnyVecVec _containers; }; diff --git a/Data/ODBC/src/Binder.cpp b/Data/ODBC/src/Binder.cpp index 38b712149..5f2e99a28 100644 --- a/Data/ODBC/src/Binder.cpp +++ b/Data/ODBC/src/Binder.cpp @@ -49,25 +49,29 @@ Binder::~Binder() void Binder::freeMemory() { - LengthVec::iterator itLen = _lengthIndicator.begin(); - LengthVec::iterator itLenEnd = _lengthIndicator.end(); - for (; itLen != itLenEnd; ++itLen) delete *itLen; + LengthPtrVec::iterator itLen = _lengthIndicator.begin(); + LengthPtrVec::iterator itLenEnd = _lengthIndicator.end(); + for(; itLen != itLenEnd; ++itLen) delete *itLen; + + LengthVecVec::iterator itVecLen = _vecLengthIndicator.begin(); + LengthVecVec::iterator itVecLenEnd = _vecLengthIndicator.end(); + for (; itVecLen != itVecLenEnd; ++itVecLen) delete *itVecLen; TimeMap::iterator itT = _times.begin(); TimeMap::iterator itTEnd = _times.end(); - for (; itT != itTEnd; ++itT) delete itT->first; + for(; itT != itTEnd; ++itT) delete itT->first; DateMap::iterator itD = _dates.begin(); DateMap::iterator itDEnd = _dates.end(); - for (; itD != itDEnd; ++itD) delete itD->first; + for(; itD != itDEnd; ++itD) delete itD->first; TimestampMap::iterator itTS = _timestamps.begin(); TimestampMap::iterator itTSEnd = _timestamps.end(); - for (; itTS != itTSEnd; ++itTS) delete itTS->first; + for(; itTS != itTSEnd; ++itTS) delete itTS->first; StringMap::iterator itStr = _strings.begin(); StringMap::iterator itStrEnd = _strings.end(); - for (; itStr != itStrEnd; ++itStr) std::free(itStr->first); + for(; itStr != itStrEnd; ++itStr) std::free(itStr->first); CharPtrVec::iterator itChr = _charPtrs.begin(); CharPtrVec::iterator endChr = _charPtrs.end(); @@ -80,6 +84,18 @@ void Binder::freeMemory() BoolPtrVec::iterator itBool = _boolPtrs.begin(); BoolPtrVec::iterator endBool = _boolPtrs.end(); for (; itBool != endBool; ++itBool) delete [] *itBool; + + DateVecVec::iterator itDateVec = _dateVecVec.begin(); + DateVecVec::iterator itDateVecEnd = _dateVecVec.end(); + for (; itDateVec != itDateVecEnd; ++itDateVec) delete *itDateVec; + + TimeVecVec::iterator itTimeVec = _timeVecVec.begin(); + TimeVecVec::iterator itTimeVecEnd = _timeVecVec.end(); + for (; itTimeVec != itTimeVecEnd; ++itTimeVec) delete *itTimeVec; + + DateTimeVecVec::iterator itDateTimeVec = _dateTimeVecVec.begin(); + DateTimeVecVec::iterator itDateTimeVecEnd = _dateTimeVecVec.end(); + for (; itDateTimeVec != itDateTimeVecEnd; ++itDateTimeVec) delete *itDateTimeVec; } @@ -385,16 +401,16 @@ void Binder::synchronize() void Binder::reset() { freeMemory(); - LengthVec().swap(_lengthIndicator); + LengthPtrVec().swap(_lengthIndicator); _inParams.clear(); _outParams.clear(); _dates.clear(); _times.clear(); _timestamps.clear(); _strings.clear(); - _dateVec.clear(); - _timeVec.clear(); - _dateTimeVec.clear(); + _dateVecVec.clear(); + _timeVecVec.clear(); + _dateTimeVecVec.clear(); _charPtrs.clear(); _boolPtrs.clear(); _containers.clear();