Fixed memory corruption issues. See code for details.

This commit is contained in:
Pietro Gagliardi 2018-06-13 08:30:00 -04:00
parent c4251894b5
commit c01b010fd7
3 changed files with 6 additions and 37 deletions

View File

@ -81,28 +81,20 @@ static LRESULT onLVN_GETDISPINFO(uiTable *t, NMLVDISPINFOW *nm)
static uiprivTableColumnParams *p;
uiTableData *data;
WCHAR *wstr;
HDC dc;
IWICBitmap *wb;
HBITMAP b;
int checked;
bool queueUpdated = false;
HRESULT hr;
wstr = t->dispinfoStrings->front();
if (wstr != NULL)
uiprivFree(wstr);
t->dispinfoStrings->pop();
p = (*(t->columns))[nm->item.iSubItem];
nm->item.pszText=L"abcdefg";
if ((nm->item.mask & LVIF_TEXT) != 0)
if (p->textModelColumn != -1) {
data = (*(t->model->mh->CellValue))(t->model->mh, t->model, nm->item.iItem, p->textModelColumn);
wstr = toUTF16(uiTableDataString(data));
uiFreeTableData(data);
nm->item.pszText = wstr;
t->dispinfoStrings->push(wstr);
queueUpdated = true;
// we could just make pszText into a freshly allocated conversion and avoid the limitation of cchTextMax
// but then we would have to keep things around for some amount of time (some pages on MSDN say 2 additional LVN_GETDISPINFO messages)
// and in practice, anything that results in extra LVN_GETDISPINFO messages (such as fillSubitemDrawParams() below) will break this counting
// TODO make it so we don't have to make a copy; instead we can convert directly into pszText (this will also avoid the risk of having a dangling surrogate pair at the end)
wcscpy_s(nm->item.pszText, nm->item.cchTextMax, wstr);
uiprivFree(wstr);
}
hr = uiprivLVN_GETDISPINFOImagesCheckboxes(t, nm, p);
@ -110,9 +102,6 @@ nm->item.pszText=L"abcdefg";
// TODO
}
// we don't want to pop from an empty queue, so if nothing updated the queue (no info was filled in above), just push NULL
if (!queueUpdated)
t->dispinfoStrings->push(NULL);
return 0;
}
@ -285,7 +274,6 @@ static void uiTableDestroy(uiControl *c)
uiTable *t = uiTable(c);
uiTableModel *model = t->model;
std::vector<uiTable *>::iterator it;
WCHAR *wstr;
uiWindowsUnregisterWM_NOTIFYHandler(t->hwnd);
uiWindowsEnsureDestroyWindow(t->hwnd);
@ -296,14 +284,6 @@ static void uiTableDestroy(uiControl *c)
break;
}
}
// empty the string queue
while (t->dispinfoStrings->size() != 0) {
wstr = t->dispinfoStrings->front();
if (wstr != NULL)
uiprivFree(wstr);
t->dispinfoStrings->pop();
}
delete t->dispinfoStrings;
// free the columns
for (auto col : *(t->columns))
uiprivFree(col);
@ -464,11 +444,6 @@ uiTable *uiNewTable(uiTableModel *model)
t->backgroundColumn = -1;
t->dispinfoStrings = new std::queue<WCHAR *>;
// this encodes the idea that two LVN_GETDISPINFOs must complete before we can free a string: the first real one is for the fourth call to free
for (i = 0; i < uiprivNumLVN_GETDISPINFOSkip; i++)
t->dispinfoStrings->push(NULL);
hr = uiprivTableSetupImagesCheckboxes(t);
if (hr != S_OK) {
// TODO

View File

@ -30,11 +30,6 @@ struct uiTable {
WPARAM nColumns;
int backgroundColumn;
// owner data state
// MSDN says we have to keep LVN_GETDISPINFO strings we allocate around at least until "two additional LVN_GETDISPINFO messages have been sent".
// we'll use this queue to do so; the "two additional" part is encoded in the initial state of the queue
std::queue<WCHAR *> *dispinfoStrings;
// tableimages.cpp
// TODO make sure what we're doing is even allowed
HIMAGELIST smallImages;

View File

@ -60,5 +60,4 @@
#include <unordered_map>
#include <sstream>
#include <functional>
#include <queue>
#endif