Checking data behind the pointer at runtime to avoid segfaults: (wchar_t *) vs. (char *)
I have a function printf
that can handle transforms %s
( char *
) and %ls
( wchar_t *
). Everything works fine if I pass in the correct argument for the correct conv pointer.
But if I pass it to char *
my function when it expects wchar_t *
, it might segfault (the null-terminated byte is, for example, in the second byte wchar_t
). Since I am referring to this argument via va_arg()
, I cannot be sure of the type.
If I believe that this array is char
always NUL terminated, I can check byte after byte to properly handle the NUL terminated char and stop memory access after it. But then I wouldn't be able to handle valid values wchar_t
like this:
0b XXXXXXXX XXXXXXXX 00000000 XXXXXXXX
I am already using the __attribute__
GNU C printf extension . But I can use this function through a python program through ctypes
, so the format / type check during compilation may not be enough.
Is there a way to do this kind of check at runtime in my C function?
(NB: "There is no such way" may be the answer, but I still ask to be completely sure.)
source to share
No, It is Immpossible.
In a typical C implementation, the type system exists only as a compile-time aid. * At runtime, all you have are data bytes, and there is no way to even point to a pointer to a number (beyond educated guesses).
Technically, you do not even allowed va_arg(ap, const char*)
, and then examine the memory, if the original argument was not char*
, signed char*
, unsigned char*
or void*
, or const
-linked version of this type. The type passed to va_arg
must always be a compatible type. (One reason for the lack of guarantee pointers for different types is the same size, layout, and value.)
(* In C ++ there is a bit more history there, because the data representing the types is stored, associated with polymorphic objects to make dynamic_cast
and typeid
work correctly, and associated with all objects, exceptions to make catch
blocks work correctly, but none of this is compatible with va_arg
.)
source to share