-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Work around the memmove bug on Samsung device #4402
Conversation
If this works.... Celebration 😄 |
is this function hooking? we used similar approach in ReactNative https://github.com/realm/realm-js/blob/master/src/android/jsc_override.cpp#L60-L126 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments, but would rather have someone from #core reviewing this.
return (*s_wrap_memmove_ptr)(dest, src, n); | ||
} | ||
|
||
static void check_memmove() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this test come from anywhere? Then a link to that would be nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -57,6 +59,8 @@ JNIEXPORT void JNICALL Java_io_realm_internal_SharedRealm_nativeInit(JNIEnv* env | |||
{ | |||
TR_ENTER() | |||
|
|||
hack_init(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be called in JNI_OnLoad or something? There is no guarantee that this code is the first native code being called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UH, yes, JNI_OnLoad()
would be a better place! But first need to make this patch work ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using __attribute__((constructor));
is also an option, if I remember it runs when the .so
is loaded https://github.com/realm/realm-js/blob/master/src/android/jsc_override.cpp#L38
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__attribute__((constructor));
looks much better, but it seems to be a gcc extension, i am not quite sure if clang support it. I will check and replace the JNI_onLoad()
if it supported by clang as well.
4e69511
to
5211cca
Compare
…o mc/bug/hack-memmove
@nhachicha no, the code you posted is really hacky 😁 It modifies the machine code in RAM during run time. This will just link to our wrapped version function during the linking time. |
s = (uint8_t*)src; | ||
while (count--) | ||
*tmp++ = *s++; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whitespace is weird here
There was a bug for memmove on some Samsung devices. The functions returns "dest + n" instead of "dest". This has been identified earlier by QT. See: https://bugreports.qt.io/browse/QTBUG-34984 The relevant android bug: https://code.google.com/p/android/issues/detail?id=81692 This fix try to test if the device have this issue first, if yes, switch to a own implementation of memmove. This fix works for most cases, but since the memmove bug existing in the system, there would be other lib/system call the buggy version of memmove which could still corrupt the memory -- which means there are still some possibilities that app gets crashed on those devices. The more hacky way is hooking into the process's code space and modify the function point to our own implementation which could solve the problem for other lib/system calls. But there is a risk that google might reject the apk for play store.
5211cca
to
dcae93b
Compare
namespace realm { | ||
namespace jni_util { | ||
|
||
void* my_bcopy(void *, const void *, std::size_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my_bcopy
sounds strange... just __bcopy
? Also, no need to have this in an independent header since it is not supposed to be used for any other places, just extern
it from the hack.cpp
?
@beeender I have asked our ops team for legal advice since we are including 3rd party code. Please do not merge before we have a clear understanding of the legal implications. |
@kneth any luck? This fix is super-duper important |
@Zhuinden We just pinged our legal. |
Sumsung? Samsung? It seems a typo on this PR's title and commit logs. |
s_wrap_memcpy_ptr = &hacked_memmove; | ||
} | ||
else { | ||
Log::i("memmove is not broken on this device - lucky you."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be logged? So many users would be lucky.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No this shouldn't be logged :)
Shame that 3.1.0 did not have this, hoping for 3.1.1 😄 |
Yes, we wil make a patch release with this as soon as legal gives a 👍 |
need to benchmark with/without wrap |
I guess the legal team said you need one with a bit more permissive license |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only nitpicking comments 👍
// See https://github.com/realm/realm-java/issues/3651#issuecomment-290290228 | ||
// There is a bug in memmove for some Samsung devices which will return "dest-n" instead of dest. | ||
// The bug was originally found by QT, see https://bugreports.qt.io/browse/QTBUG-34984 . | ||
// To work around it, we use linker's wrap feature to use a pure C implementation of memmove if the device has the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has this
size_t len = strlen(array); | ||
void* ptr = __real_memmove(array + 1, array, len - 1); | ||
if (ptr != array + 1 || strncmp(array, "FFooba", len) != 0) { | ||
Log::e("memmove is broken on this device. Switching to the builtin implementation."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
builtin
reads wrong to me here. What about Switching to a version provided by Realm
?
The underlying issue turned out to be a bug in `memmove` on some Android devices. It was addressed via realm/realm-java#4402.
Fix #3651