[WRAPPER][BOX32] Fixed unexpected bridge reuse

ftruncate and ftruncate64 point to the same native libc code on 64-bit systems, but on 32-bit x86 they are different functions. We reused bridges by native address, so a bridge made for ftruncate64 could also be used for ftruncate accidently, which breaks the latest legacy Linux Steam.

Added a new bridge key to include the wrapper too, so aliases with different guest APIs get separate bridges.
This commit is contained in:
Yang Liu committed 2026-06-29 18:02:35 +08:00
1 parent d7b78a092f
commit 148a1a21e8
1 file changed
+35 -4
+35 -4
View File
@@ -28,6 +28,17 @@
KHASH_MAP_INIT_INT128(bridgemap, uintptr_t)
typedef struct bridgekey_s {
uintptr_t fnc;
uintptr_t w;
uintptr_t fnc2;
uint16_t n;
} bridgekey_t;
#define kh_bridgekey_hash_func(key) (khint32_t)((key).fnc ^ ((key).fnc >> 33) ^ ((key).w << 7) ^ ((key).w >> 29) ^ ((key).fnc2 << 13) ^ ((key).fnc2 >> 37) ^ (key).n)
#define kh_bridgekey_hash_equal(a, b) ((a).fnc == (b).fnc && (a).w == (b).w && (a).fnc2 == (b).fnc2 && (a).n == (b).n)
KHASH_INIT(bridgewmap, bridgekey_t, uintptr_t, 1, kh_bridgekey_hash_func, kh_bridgekey_hash_equal)
typedef struct brick_s brick_t;
typedef struct brick_s {
onebridge_t *b;
@@ -41,6 +52,7 @@ typedef struct bridge_s {
brick_t *head;
brick_t *last; // to speed up
kh_bridgemap_t *bridgemap;
kh_bridgewmap_t *bridgewmap;
} bridge_t;
brick_t* NewBrick(void* old, int is32bits)
@@ -79,6 +91,7 @@ bridge_t *NewBridge()
b->head = NewBrick(load_addr, box64_is32bits);
b->last = b->head;
b->bridgemap = kh_init(bridgemap);
b->bridgewmap = kh_init(bridgewmap);
return b;
}
@@ -96,10 +109,16 @@ void FreeBridge(bridge_t** bridge)
b = n;
}
kh_destroy(bridgemap, (*bridge)->bridgemap);
kh_destroy(bridgewmap, (*bridge)->bridgewmap);
box_free(*bridge);
*bridge = NULL;
}
static bridgekey_t make_bridgekey(wrapper_t w, void* fnc, void* fnc2, int N)
{
return (bridgekey_t){(uintptr_t)fnc, (uintptr_t)w, (uintptr_t)fnc2, N};
}
//static const char* default_bridge = "bridge???";
uintptr_t AddBridge2(bridge_t* bridge, wrapper_t w, void* fnc, void* fnc2, int N, const char* name)
{
@@ -120,6 +139,9 @@ uintptr_t AddBridge2(bridge_t* bridge, wrapper_t w, void* fnc, void* fnc2, int N
khint128_t key = (uintptr_t)fnc | (khint128_t)((uintptr_t)fnc2)<<64;
khint_t k = kh_put(bridgemap, bridge->bridgemap, key, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
bridgekey_t wkey = make_bridgekey(w, fnc, fnc2, N);
k = kh_put(bridgewmap, bridge->bridgewmap, wkey, &ret);
kh_value(bridge->bridgewmap, k) = (uintptr_t)&b->b[sz].CC;
mutex_unlock(&my_context->mutex_bridge);
b->b[sz].CC = 0xCC;
@@ -158,11 +180,20 @@ uintptr_t CheckBridged2(bridge_t* bridge, void* fnc, void* fnc2)
return kh_value(bridge->bridgemap, k);
}
static uintptr_t CheckBridgedExact(bridge_t* bridge, wrapper_t w, void* fnc, void* fnc2, int N)
{
bridgekey_t key = make_bridgekey(w, fnc, fnc2, N);
khint_t k = kh_get(bridgewmap, bridge->bridgewmap, key);
if(k==kh_end(bridge->bridgewmap))
return 0;
return kh_value(bridge->bridgewmap, k);
}
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
{
if(!fnc && w)
return 0;
uintptr_t ret = CheckBridged(bridge, fnc);
uintptr_t ret = CheckBridgedExact(bridge, w, fnc, NULL, N);
if(!ret)
ret = AddBridge(bridge, w, fnc, N, name);
return ret;
@@ -172,7 +203,7 @@ uintptr_t AddCheckBridge2(bridge_t* bridge, wrapper_t w, void* fnc, void* fnc2,
{
if(!fnc && w)
return 0;
uintptr_t ret = CheckBridged2(bridge, fnc, fnc2);
uintptr_t ret = CheckBridgedExact(bridge, w, fnc, fnc2, N);
if(!ret)
ret = AddBridge2(bridge, w, fnc, fnc2, N, name);
return ret;
@@ -182,7 +213,7 @@ uintptr_t AddAutomaticBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, co
{
if(!fnc)
return 0;
uintptr_t ret = CheckBridged(bridge, fnc);
uintptr_t ret = CheckBridgedExact(bridge, w, fnc, NULL, N);
if(!ret)
ret = AddBridge(bridge, w, fnc, N, name);
if(!hasAlternate(fnc)) {
@@ -196,7 +227,7 @@ uintptr_t AddAutomaticBridgeAlt(bridge_t* bridge, wrapper_t w, void* fnc, void*
{
if(!fnc)
return 0;
uintptr_t ret = CheckBridged(bridge, alt);
uintptr_t ret = CheckBridgedExact(bridge, w, alt, NULL, N);
if(!ret)
ret = AddBridge(bridge, w, alt, N, name);
if(!hasAlternate(fnc)) {