immunant / IA2-Phase2

5 stars 0 forks source link

rewriter: fn ptr casts from `void*` (e.x. `dlsym`) unhandled #425

Open kkysen opened 1 month ago

kkysen commented 1 month ago

ia2-rewriter doesn't seem to handle the case where a function pointer is cast from a void*, such as the one returned by dlsym:

diff --git a/src/lib.c b/src/lib.c
index 4d9a2d3..7c12215 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -99,2 +99,2 @@ static COLD size_t get_stack_size_internal(const pthread_attr_t *const thread_at
-    size_t (*const get_minstack)(const pthread_attr_t*) =
+    struct IA2_fnptr__ZTSFmPK14pthread_attr_tE get_minstack =
         dlsym(RTLD_DEFAULT, "__pthread_get_minstack");

This results in a compiler error, because while there is an implicit void* to function pointer cast, there is no implicit void* to struct cast.

It doesn't seem like there is a dedicated IA2_* macro for this already, as IA2_FN requires an existing static function name to work.

We could probably do something like IA2_FN_FROM_ADDR:

diff --git a/src/lib.c b/src/lib.c
index 4d9a2d3..7c12215 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -99,2 +99,2 @@ static COLD size_t get_stack_size_internal(const pthread_attr_t *const thread_at
     struct IA2_fnptr__ZTSFmPK14pthread_attr_tE get_minstack =
-        dlsym(RTLD_DEFAULT, "__pthread_get_minstack");
+        IA2_FN_FROM_ADDR(_ZTSFmPK14pthread_attr_tE, dlsym(RTLD_DEFAULT, "__pthread_get_minstack"));

which expands to:

diff --git a/src/lib.c b/src/lib.c
index 4d9a2d3..7c12215 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -99,2 +99,2 @@ static COLD size_t get_stack_size_internal(const pthread_attr_t *const thread_at
     struct IA2_fnptr__ZTSFmPK14pthread_attr_tE get_minstack =
-        dlsym(RTLD_DEFAULT, "__pthread_get_minstack");
+        (struct IA2_fnptr__ZTSFmPK14pthread_attr_tE) { .ptr = dlsym(RTLD_DEFAULT, "__pthread_get_minstack") };
ayrtonm commented 1 month ago

To summarize discussions on slack: going from a fn ptr struct to void * is fine, but going the other direction requires the user to verify that the void * was derived from a fn ptr. In this case the fact that the void * came from dlsym complicates things.