st/nine: Refactor ht_guid_delete

Have ht_guid_delete take a hash_entry.

As a result, we can use _mesa_hash_table_remove instead of
_mesa_hash_table_remove_key.
The previous code using the latter was incorrect as the key
of the entry was read after it was freed.

Fixes: https://github.com/iXit/wine-nine-standalone/issues/40

Signed-off-by: Axel Davy <davyaxel0@gmail.com>
Acked-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9177>
This commit is contained in:
Axel Davy 2021-01-31 20:04:40 +01:00
parent 501ad0e134
commit b383b1e01a
2 changed files with 19 additions and 20 deletions

View file

@ -22,7 +22,7 @@
#include "iunknown.h"
#include "util/u_atomic.h"
#include "util/u_hash_table.h"
#include "util/hash_table.h"
#include "nine_helpers.h"
#include "nine_pdata.h"
@ -72,10 +72,8 @@ NineUnknown_dtor( struct NineUnknown *This )
if (This->refs && This->device) /* Possible only if early exit after a ctor failed */
(void) NineUnknown_Release(NineUnknown(This->device));
if (This->pdata) {
util_hash_table_foreach(This->pdata, ht_guid_delete, NULL);
_mesa_hash_table_destroy(This->pdata, NULL);
}
if (This->pdata)
_mesa_hash_table_destroy(This->pdata, ht_guid_delete);
FREE(This);
}
@ -235,6 +233,7 @@ NineUnknown_GetPrivateData( struct NineUnknown *This,
void *pData,
DWORD *pSizeOfData )
{
struct hash_entry *entry;
struct pheader *header;
DWORD sizeofdata;
char guid_str[64];
@ -245,8 +244,10 @@ NineUnknown_GetPrivateData( struct NineUnknown *This,
(void)guid_str;
header = util_hash_table_get(This->pdata, refguid);
if (!header) { DBG("Returning D3DERR_NOTFOUND\n"); return D3DERR_NOTFOUND; }
entry = _mesa_hash_table_search(This->pdata, refguid);
if (!entry) { DBG("Returning D3DERR_NOTFOUND\n"); return D3DERR_NOTFOUND; }
header = entry->data;
user_assert(pSizeOfData, E_POINTER);
sizeofdata = *pSizeOfData;
@ -274,22 +275,22 @@ HRESULT NINE_WINAPI
NineUnknown_FreePrivateData( struct NineUnknown *This,
REFGUID refguid )
{
struct pheader *header;
struct hash_entry *entry;
char guid_str[64];
DBG("This=%p GUID=%s\n", This, GUID_sprintf(guid_str, refguid));
(void)guid_str;
header = util_hash_table_get(This->pdata, refguid);
if (!header) {
entry = _mesa_hash_table_search(This->pdata, refguid);
if (!entry) {
DBG("Nothing to free\n");
return D3DERR_NOTFOUND;
}
DBG("Freeing %p\n", header);
ht_guid_delete(NULL, header, NULL);
_mesa_hash_table_remove_key(This->pdata, refguid);
DBG("Freeing %p\n", entry->data);
ht_guid_delete(entry);
_mesa_hash_table_remove(This->pdata, entry);
return D3D_OK;
}

View file

@ -2,6 +2,8 @@
#ifndef _NINE_PDATA_H_
#define _NINE_PDATA_H_
#include "util/hash_table.h"
struct pheader
{
boolean unknown;
@ -29,18 +31,14 @@ ht_guid_hash( const void *key )
return hash;
}
static enum pipe_error
ht_guid_delete( void *key,
void *value,
void *data )
static void
ht_guid_delete( struct hash_entry *entry )
{
struct pheader *header = value;
struct pheader *header = entry->data;
void *header_data = (void *)header + sizeof(*header);
if (header->unknown) { IUnknown_Release(*(IUnknown **)header_data); }
FREE(header);
return PIPE_OK;
}
#endif /* _NINE_PDATA_H_ */