Former title was: crash on vsprintf
starting from Android12 (api >= 31)
My Android app uses a native library (libexif) built with NDK. At some time in my native code (adapted from exif), I call the vsprintf
function which makes the app crash. Formerly in exif, it was a call to vfprintf (stderr, format, args);
that I replaced by vsprintf
so as to store the string for later use.
static void
log_func (ExifLog *log, ExifLogCode code, const char *domain,
const char *format, va_list args, void *data)
{
char dest[1024] = {0, };
vsprintf(dest, format, args);
}
The message (as per the output from an API where it works) should be:
The tag 'ComponentsConfiguration' contains an invalid number of components (3, expected 4).
The format
variable contains: " The tag '%s' contains an invalid number of components (%i, expected %i).
"
I couldn't check the values of the arguments (haven't found how to print them to check their values).
This works without any problems up to API30 (on the emulator). On an image using API31 it crashes at the call of the vsprintf
function.
Updating NDK to 25b doesn't fix either. My API30 image is x86, the API31 image is x86_64.
Any idea to fix/workaround this?
Other parts of code that may be of interest:
#ifndef NO_VERBOSE_TAG_STRINGS
static void
exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
{
va_list args;
ExifLog *l = NULL;
if (e && e->parent && e->parent->parent)
l = exif_data_get_log (e->parent->parent);
va_start (args, format);
exif_logv (l, code, "ExifEntry", format, args);
va_end (args);
}
#else
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define exif_entry_log(...) do { } while (0)
#elif defined(__GNUC__)
#define exif_entry_log(x...) do { } while (0)
#else
#define exif_entry_log (void)
#endif
#endif
#define CC(entry,target,v,maxlen) \
{ \
if (entry->components != target) { \
exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA, \
_("The tag '%s' contains an invalid number of " \
"components (%i, expected %i)."), \
exif_tag_get_name (entry->tag), \
(int) entry->components, (int) target); \
break; \
} \
}
// Then this call later
CC (e, 4, val, maxlen);
In the meantime since API30 images have x86 arch, and API31 images are x86_64 I just tried API30 with a x86_64. For now:
So this looks like it is x86 vs x86_64 emulator image related.
On a real arm8 device, there is no crash either.
I also found that the args passed to vsprintf
don't have the expected values. And If a simulate vsprintf
with the expected values, vsprintf
works fine. So the problem is likely not vsprintf
.
The cause of the problem was that I was using args
twice: Once in vsprintf
and once in vsprintf
.
This is now allowed according to https://stackoverflow.com/a/10807375/15401262 and leads to undefined behavior.
It can't be used twice and one has to use va_copy in that case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.