Skip to content

Commit

Permalink
Fixing an issue where we would read out of bounds if we were spying o…
Browse files Browse the repository at this point in the history
…n an object (#8)
  • Loading branch information
AlexTroyer authored Jul 28, 2023
1 parent ed410f7 commit ec6df8f
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 107 deletions.
2 changes: 1 addition & 1 deletion include/fakeit/MockImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ namespace fakeit {

MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
: _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
, _proxy{obj}
, _proxy{obj, isSpy}
, _fakeit(fakeit) {}

static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
Expand Down
10 changes: 6 additions & 4 deletions include/mockutils/DynamicProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ namespace fakeit {

static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

DynamicProxy(C &inst) :
DynamicProxy(C &inst, bool isUsingSpy) :
instance(inst),
originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
_methodMocks(VTUtils::getVTSize<C>()),
_offsets(VTUtils::getVTSize<C>()),
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_invocationHandlers(_methodMocks, _offsets),
_isUsingSpy(isUsingSpy) {
_cloneVt.copyFrom(originalVtHandle.restore(), isUsingSpy);
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
getFake().setVirtualTable(_cloneVt);
}
Expand All @@ -93,7 +94,7 @@ namespace fakeit {
_members = {};
_offsets = {};
_offsets.resize(VTUtils::getVTSize<C>());
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.copyFrom(originalVtHandle.restore(), _isUsingSpy);
}

void Clear()
Expand Down Expand Up @@ -191,6 +192,7 @@ namespace fakeit {
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;
bool _isUsingSpy = false;

FakeObject<C, baseclasses...> &getFake() {
return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
Expand Down
2 changes: 1 addition & 1 deletion include/mockutils/gcc/VirtualTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool) {
unsigned int size = VTUtils::getVTSize<C>();
//firstMethod[-1] = from.firstMethod[-1]; // copy type_info
for (size_t i = 0; i < size; ++i) {
Expand Down
6 changes: 4 additions & 2 deletions include/mockutils/mscpp/VirtualTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,14 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool isUsingSpy) {
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
if (VTUtils::hasVirtualDestructor<C>())
// Only try to get the cookie if we aren't using a spy. If we aren't using a spy
// we end up indexing out of bounds and reading garbage memory
if (VTUtils::hasVirtualDestructor<C>() && !isUsingSpy)
setCookie(dtorCookieIndex, from.getCookie(dtorCookieIndex));
}

Expand Down
22 changes: 13 additions & 9 deletions single_header/boost/fakeit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* FakeIt - A Simplified C++ Mocking Framework
* Copyright (c) Eran Pe'er 2013
* Generated: 2023-03-20 07:43:23.626171
* Generated: 2023-07-08 18:53:41.524047
* Distributed under the MIT License. Please refer to the LICENSE file at:
* https://github.com/eranpeer/FakeIt
*/
Expand Down Expand Up @@ -5524,12 +5524,14 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool isUsingSpy) {
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
if (VTUtils::hasVirtualDestructor<C>())


if (VTUtils::hasVirtualDestructor<C>() && !isUsingSpy)
setCookie(dtorCookieIndex, from.getCookie(dtorCookieIndex));
}

Expand Down Expand Up @@ -5702,7 +5704,7 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool) {
unsigned int size = VTUtils::getVTSize<C>();

for (size_t i = 0; i < size; ++i) {
Expand Down Expand Up @@ -5987,13 +5989,14 @@ namespace fakeit {

static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

DynamicProxy(C &inst) :
DynamicProxy(C &inst, bool isUsingSpy) :
instance(inst),
originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
_methodMocks(VTUtils::getVTSize<C>()),
_offsets(VTUtils::getVTSize<C>()),
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_invocationHandlers(_methodMocks, _offsets),
_isUsingSpy(isUsingSpy) {
_cloneVt.copyFrom(originalVtHandle.restore(), isUsingSpy);
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
getFake().setVirtualTable(_cloneVt);
}
Expand All @@ -6016,7 +6019,7 @@ namespace fakeit {
_members = {};
_offsets = {};
_offsets.resize(VTUtils::getVTSize<C>());
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.copyFrom(originalVtHandle.restore(), _isUsingSpy);
}

void Clear()
Expand Down Expand Up @@ -6114,6 +6117,7 @@ namespace fakeit {
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;
bool _isUsingSpy = false;

FakeObject<C, baseclasses...> &getFake() {
return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
Expand Down Expand Up @@ -8608,7 +8612,7 @@ namespace fakeit {

MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
: _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
, _proxy{obj}
, _proxy{obj, isSpy}
, _fakeit(fakeit) {}

static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
Expand Down
22 changes: 13 additions & 9 deletions single_header/catch/fakeit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* FakeIt - A Simplified C++ Mocking Framework
* Copyright (c) Eran Pe'er 2013
* Generated: 2023-03-20 07:43:23.696244
* Generated: 2023-07-08 18:53:41.573198
* Distributed under the MIT License. Please refer to the LICENSE file at:
* https://github.com/eranpeer/FakeIt
*/
Expand Down Expand Up @@ -5562,12 +5562,14 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool isUsingSpy) {
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
if (VTUtils::hasVirtualDestructor<C>())


if (VTUtils::hasVirtualDestructor<C>() && !isUsingSpy)
setCookie(dtorCookieIndex, from.getCookie(dtorCookieIndex));
}

Expand Down Expand Up @@ -5740,7 +5742,7 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool) {
unsigned int size = VTUtils::getVTSize<C>();

for (size_t i = 0; i < size; ++i) {
Expand Down Expand Up @@ -6025,13 +6027,14 @@ namespace fakeit {

static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

DynamicProxy(C &inst) :
DynamicProxy(C &inst, bool isUsingSpy) :
instance(inst),
originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
_methodMocks(VTUtils::getVTSize<C>()),
_offsets(VTUtils::getVTSize<C>()),
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_invocationHandlers(_methodMocks, _offsets),
_isUsingSpy(isUsingSpy) {
_cloneVt.copyFrom(originalVtHandle.restore(), isUsingSpy);
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
getFake().setVirtualTable(_cloneVt);
}
Expand All @@ -6054,7 +6057,7 @@ namespace fakeit {
_members = {};
_offsets = {};
_offsets.resize(VTUtils::getVTSize<C>());
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.copyFrom(originalVtHandle.restore(), _isUsingSpy);
}

void Clear()
Expand Down Expand Up @@ -6152,6 +6155,7 @@ namespace fakeit {
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;
bool _isUsingSpy = false;

FakeObject<C, baseclasses...> &getFake() {
return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
Expand Down Expand Up @@ -8646,7 +8650,7 @@ namespace fakeit {

MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
: _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
, _proxy{obj}
, _proxy{obj, isSpy}
, _fakeit(fakeit) {}

static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
Expand Down
22 changes: 13 additions & 9 deletions single_header/cute/fakeit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* FakeIt - A Simplified C++ Mocking Framework
* Copyright (c) Eran Pe'er 2013
* Generated: 2023-03-20 07:43:23.751162
* Generated: 2023-07-08 18:53:41.621542
* Distributed under the MIT License. Please refer to the LICENSE file at:
* https://github.com/eranpeer/FakeIt
*/
Expand Down Expand Up @@ -5489,12 +5489,14 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool isUsingSpy) {
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
if (VTUtils::hasVirtualDestructor<C>())


if (VTUtils::hasVirtualDestructor<C>() && !isUsingSpy)
setCookie(dtorCookieIndex, from.getCookie(dtorCookieIndex));
}

Expand Down Expand Up @@ -5667,7 +5669,7 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool) {
unsigned int size = VTUtils::getVTSize<C>();

for (size_t i = 0; i < size; ++i) {
Expand Down Expand Up @@ -5952,13 +5954,14 @@ namespace fakeit {

static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

DynamicProxy(C &inst) :
DynamicProxy(C &inst, bool isUsingSpy) :
instance(inst),
originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
_methodMocks(VTUtils::getVTSize<C>()),
_offsets(VTUtils::getVTSize<C>()),
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_invocationHandlers(_methodMocks, _offsets),
_isUsingSpy(isUsingSpy) {
_cloneVt.copyFrom(originalVtHandle.restore(), isUsingSpy);
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
getFake().setVirtualTable(_cloneVt);
}
Expand All @@ -5981,7 +5984,7 @@ namespace fakeit {
_members = {};
_offsets = {};
_offsets.resize(VTUtils::getVTSize<C>());
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.copyFrom(originalVtHandle.restore(), _isUsingSpy);
}

void Clear()
Expand Down Expand Up @@ -6079,6 +6082,7 @@ namespace fakeit {
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;
bool _isUsingSpy = false;

FakeObject<C, baseclasses...> &getFake() {
return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
Expand Down Expand Up @@ -8573,7 +8577,7 @@ namespace fakeit {

MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
: _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
, _proxy{obj}
, _proxy{obj, isSpy}
, _fakeit(fakeit) {}

static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
Expand Down
22 changes: 13 additions & 9 deletions single_header/doctest/fakeit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* FakeIt - A Simplified C++ Mocking Framework
* Copyright (c) Eran Pe'er 2013
* Generated: 2023-03-20 07:43:23.814100
* Generated: 2023-07-08 18:53:41.670237
* Distributed under the MIT License. Please refer to the LICENSE file at:
* https://github.com/eranpeer/FakeIt
*/
Expand Down Expand Up @@ -5517,12 +5517,14 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool isUsingSpy) {
auto size = VTUtils::getVTSize<C>();
for (unsigned int i = 0; i < size; i++) {
_firstMethod[i] = from.getMethod(i);
}
if (VTUtils::hasVirtualDestructor<C>())


if (VTUtils::hasVirtualDestructor<C>() && !isUsingSpy)
setCookie(dtorCookieIndex, from.getCookie(dtorCookieIndex));
}

Expand Down Expand Up @@ -5695,7 +5697,7 @@ namespace fakeit {
return *vt;
}

void copyFrom(VirtualTable<C, baseclasses...> &from) {
void copyFrom(VirtualTable<C, baseclasses...> &from, bool) {
unsigned int size = VTUtils::getVTSize<C>();

for (size_t i = 0; i < size; ++i) {
Expand Down Expand Up @@ -5980,13 +5982,14 @@ namespace fakeit {

static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

DynamicProxy(C &inst) :
DynamicProxy(C &inst, bool isUsingSpy) :
instance(inst),
originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
_methodMocks(VTUtils::getVTSize<C>()),
_offsets(VTUtils::getVTSize<C>()),
_invocationHandlers(_methodMocks, _offsets) {
_cloneVt.copyFrom(originalVtHandle.restore());
_invocationHandlers(_methodMocks, _offsets),
_isUsingSpy(isUsingSpy) {
_cloneVt.copyFrom(originalVtHandle.restore(), isUsingSpy);
_cloneVt.setCookie(InvocationHandlerCollection::VtCookieIndex, &_invocationHandlers);
getFake().setVirtualTable(_cloneVt);
}
Expand All @@ -6009,7 +6012,7 @@ namespace fakeit {
_members = {};
_offsets = {};
_offsets.resize(VTUtils::getVTSize<C>());
_cloneVt.copyFrom(originalVtHandle.restore());
_cloneVt.copyFrom(originalVtHandle.restore(), _isUsingSpy);
}

void Clear()
Expand Down Expand Up @@ -6107,6 +6110,7 @@ namespace fakeit {
std::vector<std::shared_ptr<Destructible>> _members;
std::vector<size_t> _offsets;
InvocationHandlers _invocationHandlers;
bool _isUsingSpy = false;

FakeObject<C, baseclasses...> &getFake() {
return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
Expand Down Expand Up @@ -8601,7 +8605,7 @@ namespace fakeit {

MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
: _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
, _proxy{obj}
, _proxy{obj, isSpy}
, _fakeit(fakeit) {}

static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
Expand Down
Loading

0 comments on commit ec6df8f

Please sign in to comment.