GH #512: Poco:Data:ODBC:Binder.h causes a crash

This commit is contained in:
Alex Fabijanic 2014-10-10 21:12:44 -05:00
parent e719228861
commit 63a9c7cd2a
3 changed files with 123 additions and 74 deletions

View File

@ -38,7 +38,7 @@ Release 1.5.4 (2014-10-13)
- HTTPCookie: fix documentation for max age - HTTPCookie: fix documentation for max age
- added Timestamp::raw() and Clock::raw() - added Timestamp::raw() and Clock::raw()
- Poco::Buffer properly handles zero-sized buffers - Poco::Buffer properly handles zero-sized buffers
- GH #512: Poco:Data:ODBC:Binder.h causes a crash
Release 1.5.3 (2014-06-30) Release 1.5.3 (2014-06-30)
========================== ==========================

View File

@ -353,15 +353,20 @@ public:
/// Clears the cached storage. /// Clears the cached storage.
private: private:
typedef std::vector<SQLLEN*> LengthVec; typedef std::vector<SQLLEN*> LengthPtrVec;
typedef std::vector<std::vector<SQLLEN> > LengthVecVec; typedef std::vector<SQLLEN> LengthVec;
typedef std::vector<LengthVec*> LengthVecVec;
typedef std::vector<char*> CharPtrVec; typedef std::vector<char*> CharPtrVec;
typedef std::vector<UTF16Char*> UTF16CharPtrVec; typedef std::vector<UTF16Char*> UTF16CharPtrVec;
typedef std::vector<bool*> BoolPtrVec; typedef std::vector<bool*> BoolPtrVec;
typedef std::vector<std::vector<SQL_DATE_STRUCT> > DateVec; typedef std::vector<SQL_DATE_STRUCT> DateVec;
typedef std::vector<std::vector<SQL_TIME_STRUCT> > TimeVec; typedef std::vector<DateVec*> DateVecVec;
typedef std::vector<std::vector<SQL_TIMESTAMP_STRUCT> > DateTimeVec; typedef std::vector<SQL_TIME_STRUCT> TimeVec;
typedef std::vector<std::vector<Poco::Any> > AnyVec; typedef std::vector<TimeVec*> TimeVecVec;
typedef std::vector<SQL_TIMESTAMP_STRUCT> DateTimeVec;
typedef std::vector<DateTimeVec*> DateTimeVecVec;
typedef std::vector<Poco::Any> AnyVec;
typedef std::vector<AnyVec> AnyVecVec;
typedef std::map<char*, std::string*> StringMap; typedef std::map<char*, std::string*> StringMap;
typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap; typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap;
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap; typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
@ -450,8 +455,8 @@ private:
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(length, sizeof(T)); _vecLengthIndicator[pos] = new LengthVec(length);
} }
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
@ -463,7 +468,7 @@ private:
decDigits, decDigits,
(SQLPOINTER) &val[0], (SQLPOINTER) &val[0],
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter()"); throw StatementException(_rStmt, "SQLBindParameter()");
} }
@ -502,8 +507,8 @@ private:
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(length, sizeof(bool)); _vecLengthIndicator[pos] = new LengthVec(length);
} }
if (_boolPtrs.size() <= pos) if (_boolPtrs.size() <= pos)
@ -524,7 +529,7 @@ private:
decDigits, decDigits,
(SQLPOINTER) &_boolPtrs[pos][0], (SQLPOINTER) &_boolPtrs[pos][0],
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter()"); throw StatementException(_rStmt, "SQLBindParameter()");
} }
@ -540,10 +545,12 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately."); 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."); throw InvalidArgumentException("Empty container not allowed.");
setParamSetSize(val.size()); setParamSetSize(length);
SQLINTEGER size = 0; SQLINTEGER size = 0;
getColumnOrParameterSize(pos, size); getColumnOrParameterSize(pos, size);
@ -558,8 +565,8 @@ private:
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), SQL_NTS); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS);
} }
if (_charPtrs.size() <= pos) if (_charPtrs.size() <= pos)
@ -589,7 +596,7 @@ private:
0, 0,
_charPtrs[pos], _charPtrs[pos],
(SQLINTEGER) size, (SQLINTEGER) size,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)"); throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)");
} }
@ -605,7 +612,8 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately."); 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."); throw InvalidArgumentException("Empty container not allowed.");
setParamSetSize(val.size()); setParamSetSize(val.size());
@ -623,8 +631,8 @@ private:
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), SQL_NTS); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS);
} }
if (_utf16CharPtrs.size() <= pos) if (_utf16CharPtrs.size() <= pos)
@ -654,7 +662,7 @@ private:
0, 0,
_utf16CharPtrs[pos], _utf16CharPtrs[pos],
(SQLINTEGER)size, (SQLINTEGER)size,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(std::vector<UTF16String>)"); throw StatementException(_rStmt, "SQLBindParameter(std::vector<UTF16String>)");
} }
@ -672,19 +680,22 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately."); 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."); throw InvalidArgumentException("Empty container not allowed.");
setParamSetSize(val.size()); setParamSetSize(length);
SQLINTEGER size = 0; SQLINTEGER size = 0;
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
_vecLengthIndicator.resize(pos + 1); {
_vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size()); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
std::vector<SQLLEN>::iterator lIt = _vecLengthIndicator[pos].begin(); }
std::vector<SQLLEN>::iterator lEnd = _vecLengthIndicator[pos].end();
std::vector<SQLLEN>::iterator lIt = _vecLengthIndicator[pos]->begin();
std::vector<SQLLEN>::iterator lEnd = _vecLengthIndicator[pos]->end();
typename C::const_iterator cIt = val.begin(); typename C::const_iterator cIt = val.begin();
for (; lIt != lEnd; ++lIt, ++cIt) for (; lIt != lEnd; ++lIt, ++cIt)
{ {
@ -721,7 +732,7 @@ private:
0, 0,
_charPtrs[pos], _charPtrs[pos],
(SQLINTEGER) size, (SQLINTEGER) size,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(std::vector<BLOB>)"); throw StatementException(_rStmt, "SQLBindParameter(std::vector<BLOB>)");
} }
@ -736,21 +747,28 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately."); 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."); throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(val.size()); setParamSetSize(length);
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT); SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), size); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
} }
if (_dateVec.size() <= pos) _dateVec.resize(pos + 1); if (_dateVecVec.size() <= pos)
Utility::dateSync(_dateVec[pos], val); {
_dateVecVec.resize(pos + 1, 0);
_dateVecVec[pos] = new DateVec(length ? length : 1);
}
Utility::dateSync(*_dateVecVec[pos], val);
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
@ -763,9 +781,9 @@ private:
SQL_TYPE_DATE, SQL_TYPE_DATE,
colSize, colSize,
decDigits, decDigits,
(SQLPOINTER) &_dateVec[pos][0], (SQLPOINTER) &(*_dateVecVec[pos])[0],
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(Date[])"); throw StatementException(_rStmt, "SQLBindParameter(Date[])");
} }
@ -780,7 +798,8 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately."); 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."); throw InvalidArgumentException("Empty container not allowed.");
setParamSetSize(val.size()); setParamSetSize(val.size());
@ -789,12 +808,17 @@ private:
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), size); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
} }
if (_timeVec.size() <= pos) _timeVec.resize(pos + 1); if (_timeVecVec.size() <= pos)
Utility::timeSync(_timeVec[pos], val); {
_timeVecVec.resize(pos + 1, 0);
_timeVecVec[pos] = new TimeVec(length ? length : 1);
}
Utility::timeSync(*_timeVecVec[pos], val);
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
@ -807,9 +831,9 @@ private:
SQL_TYPE_TIME, SQL_TYPE_TIME,
colSize, colSize,
decDigits, decDigits,
(SQLPOINTER) &_timeVec[pos][0], (SQLPOINTER) &(*_timeVecVec[pos])[0],
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(Time[])"); throw StatementException(_rStmt, "SQLBindParameter(Time[])");
} }
@ -824,21 +848,28 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately."); 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."); throw InvalidArgumentException("Empty Containers not allowed.");
setParamSetSize(val.size()); setParamSetSize(length);
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT); SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT);
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), size); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
} }
if (_dateTimeVec.size() <= pos) _dateTimeVec.resize(pos + 1); if (_dateTimeVecVec.size() <= pos)
Utility::dateTimeSync(_dateTimeVec[pos], val); {
_dateTimeVecVec.resize(pos + 1, 0);
_dateTimeVecVec[pos] = new DateTimeVec(length ? length : 1);
}
Utility::dateTimeSync(*_dateTimeVecVec[pos], val);
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
@ -851,9 +882,9 @@ private:
SQL_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP,
colSize, colSize,
decDigits, decDigits,
(SQLPOINTER) &_dateTimeVec[pos][0], (SQLPOINTER) &(*_dateTimeVecVec[pos])[0],
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter(Time[])"); throw StatementException(_rStmt, "SQLBindParameter(Time[])");
} }
@ -868,17 +899,19 @@ private:
if (PB_IMMEDIATE != _paramBinding) if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Container can only be bound immediately."); 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."); throw InvalidArgumentException("Empty container not allowed.");
setParamSetSize(val.size()); setParamSetSize(length);
SQLINTEGER size = SQL_NULL_DATA; SQLINTEGER size = SQL_NULL_DATA;
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1); _vecLengthIndicator.resize(pos + 1, 0);
_vecLengthIndicator[pos].resize(val.size(), size); _vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
} }
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
@ -894,7 +927,7 @@ private:
decDigits, decDigits,
0, 0,
0, 0,
&_vecLengthIndicator[pos][0]))) &(*_vecLengthIndicator[pos])[0])))
{ {
throw StatementException(_rStmt, "SQLBindParameter()"); throw StatementException(_rStmt, "SQLBindParameter()");
} }
@ -956,7 +989,7 @@ private:
const StatementHandle& _rStmt; const StatementHandle& _rStmt;
LengthVec _lengthIndicator; LengthPtrVec _lengthIndicator;
LengthVecVec _vecLengthIndicator; LengthVecVec _vecLengthIndicator;
ParamMap _inParams; ParamMap _inParams;
@ -969,16 +1002,16 @@ private:
StringMap _strings; StringMap _strings;
UTF16StringMap _utf16Strings; UTF16StringMap _utf16Strings;
DateVec _dateVec; DateVecVec _dateVecVec;
TimeVec _timeVec; TimeVecVec _timeVecVec;
DateTimeVec _dateTimeVec; DateTimeVecVec _dateTimeVecVec;
CharPtrVec _charPtrs; CharPtrVec _charPtrs;
UTF16CharPtrVec _utf16CharPtrs; UTF16CharPtrVec _utf16CharPtrs;
BoolPtrVec _boolPtrs; BoolPtrVec _boolPtrs;
const TypeInfo* _pTypeInfo; const TypeInfo* _pTypeInfo;
SQLINTEGER _paramSetSize; SQLINTEGER _paramSetSize;
std::size_t _maxFieldSize; std::size_t _maxFieldSize;
AnyVec _containers; AnyVecVec _containers;
}; };

View File

@ -49,25 +49,29 @@ Binder::~Binder()
void Binder::freeMemory() void Binder::freeMemory()
{ {
LengthVec::iterator itLen = _lengthIndicator.begin(); LengthPtrVec::iterator itLen = _lengthIndicator.begin();
LengthVec::iterator itLenEnd = _lengthIndicator.end(); LengthPtrVec::iterator itLenEnd = _lengthIndicator.end();
for (; itLen != itLenEnd; ++itLen) delete *itLen; 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 itT = _times.begin();
TimeMap::iterator itTEnd = _times.end(); 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 itD = _dates.begin();
DateMap::iterator itDEnd = _dates.end(); 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 itTS = _timestamps.begin();
TimestampMap::iterator itTSEnd = _timestamps.end(); 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 itStr = _strings.begin();
StringMap::iterator itStrEnd = _strings.end(); 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 itChr = _charPtrs.begin();
CharPtrVec::iterator endChr = _charPtrs.end(); CharPtrVec::iterator endChr = _charPtrs.end();
@ -80,6 +84,18 @@ void Binder::freeMemory()
BoolPtrVec::iterator itBool = _boolPtrs.begin(); BoolPtrVec::iterator itBool = _boolPtrs.begin();
BoolPtrVec::iterator endBool = _boolPtrs.end(); BoolPtrVec::iterator endBool = _boolPtrs.end();
for (; itBool != endBool; ++itBool) delete [] *itBool; 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() void Binder::reset()
{ {
freeMemory(); freeMemory();
LengthVec().swap(_lengthIndicator); LengthPtrVec().swap(_lengthIndicator);
_inParams.clear(); _inParams.clear();
_outParams.clear(); _outParams.clear();
_dates.clear(); _dates.clear();
_times.clear(); _times.clear();
_timestamps.clear(); _timestamps.clear();
_strings.clear(); _strings.clear();
_dateVec.clear(); _dateVecVec.clear();
_timeVec.clear(); _timeVecVec.clear();
_dateTimeVec.clear(); _dateTimeVecVec.clear();
_charPtrs.clear(); _charPtrs.clear();
_boolPtrs.clear(); _boolPtrs.clear();
_containers.clear(); _containers.clear();