You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TLDR: 4 bytes buffer allocated from apmpb_copy_measurement_bundle + 1900 is being written 8 bytes using nano_set_uint32 from APMUpdateConsentSignalsAndIdentifiers + 236
Full description:
Here is more detailed steps how corruption happen:
A buffer of size 4 bytes allocated by apmpb_copy_measurement_bundle + 1900:
at that point write watchpoint is added for memory location $x0+4 (outside of the buffer)
Then write watchpoint catch that 8 bytes are written to the buffer by nano_set_uint32 called from APMUpdateConsentSignalsAndIdentifiers + 236 via intermediate call to NANOSetInt32 + 140:
The suspicious thing is that nano_set_uint32 could allocate buffer by itself, but it uses 8 bytes as buffer size, so it is likely that provided buffer must be at least 8 bytes:
nano_set_uint32:...mov w0, #0x8bl0x10daca894 ; symbol stub for: malloc...
It is interesting why function which has uint32 in name does allocate 8 bytes, instead of intuitevely guessable 4 bytes.
It also interesting why it does 8 bytes-wide write while function name suggest 32-bit wide argument.
Here is the disassembly of provided by lldb:
App`nano_set_uint32:
0x10961423c : cbz x0, 0x10961427c ;
0x109614240 : stp x20, x19, [sp, #-0x20]!
0x109614244 : stp x29, x30, [sp, #0x10]
0x109614248 : add x29, sp, #0x10
0x10961424c : mov x19, x1 # note: second func argument seems to be 64-bit integer
0x109614250 : mov x20, x0 # note: first func argument seems to be pointer
0x109614254 : ldr x0, [x0]
0x109614258 : cbnz x0, 0x109614268 ;
0x10961425c : mov w0, #0x8
0x109614260 : bl 0x10a2fe894 ; symbol stub for: malloc
0x109614264 : str x0, [x20]
0x109614268 : mov w8, w19 # note: looks like implementation of truncation of 64-bit integer down to 32-bit integer with zero-extension (https://devblogs.microsoft.com/oldnewthing/20220805-00/)
-> 0x10961426c : str x8, [x0] # note: 8 bytes write to [$x0] happen here
0x109614270 : ldp x29, x30, [sp, #0x10]
0x109614274 : ldp x20, x19, [sp], #0x20
0x109614278 : ret
0x10961427c : adrp x0, 4328
0x109614280 : add x0, x0, #0x7ee ; " Unable to set uint32. Destination pointer is NULL"
0x109614284 : b 0x10a2fef18 ; symbol stub for: puts
Using godbolt.org I've reconstructed the possible definitioon of nano_set_uint32 in C language:
voidnano_set_uint32(uint64_t**ptr/*ptr to 64-bit wide data*/, int64_tvalue/*64-bit wide data*/) {
if (NULL==ptr) {
puts(" Unable to set uint32. Destination pointer is NULL");
return;
}
if (NULL==*ptr) {
*ptr= (uint64_t*)malloc(sizeof(uint64_t));
}
**ptr= (uint32_t)value;
}
such that generated assembly by clang 16 with -O2 optimization produces almost the same assembly with the difference in one instruction which I believe effectively does the same thing - 64-bit to 32-bit integer truncation:
mov w8, w19 # instruction from Firebase binary
and x8, x19, #0xffffffff # instruction from Godbolt of re-constructed function
There is obviously something wrong here, either apmpb_copy_measurement_bundle should allocate larger buffer or nano_set_uint32 should not do 8 bytes write.
It also seems that somewhere (silent?) conversion from uint32_t* to uint64_t* done, leading to buffer overflow later.
Could you please inspect related part of Firebase SDK source code and fix buffer overflow problem?
This issue is probably harmful due to smallest malloc block allocated on iOS is actually 16 bytes, but this overrun mess with runtime diagnostic tools, in my case mimalloc with debug checks enabled.
Reproducing the issue
Use Firebase SDK in such a way that it uploads data to it's server.
Firebase SDK Version
10.10.0
Xcode Version
14.3.1
Installation Method
Swift Package Manager
Firebase Product(s)
All
Targeted Platforms
iOS
Relevant Log Output
No response
If using Swift Package Manager, the project's Package.resolved
No response
If using CocoaPods, the project's Podfile.lock
No response
The text was updated successfully, but these errors were encountered:
Hello, @paulb777 ! I was wondering if there might be an update available regarding the resolution of this issue. Do you need any additional information to facilitate the investigation and rectification of the bug? Thank you for your time and effort.
Thank you @mstyura for the thorough report. It'll take some time for us to look into this issue and fully test a fix. Unfortunately, the fix won't make it into our July release.
Description
TLDR: 4 bytes buffer allocated from
apmpb_copy_measurement_bundle + 1900
is being written 8 bytes usingnano_set_uint32
fromAPMUpdateConsentSignalsAndIdentifiers + 236
Full description:
Here is more detailed steps how corruption happen:
apmpb_copy_measurement_bundle + 1900
:backtrace of 4 bytes block allocation:
at that point write watchpoint is added for memory location $x0+4 (outside of the buffer)
nano_set_uint32
called fromAPMUpdateConsentSignalsAndIdentifiers + 236
via intermediate call toNANOSetInt32 + 140
:backtrace of 8 bytes write to 4 byte buffer:
The suspicious thing is that
nano_set_uint32
could allocate buffer by itself, but it uses8
bytes as buffer size, so it is likely that provided buffer must be at least8
bytes:It is interesting why function which has
uint32
in name does allocate8
bytes, instead of intuitevely guessable4
bytes.It also interesting why it does
8
bytes-wide write while function name suggest 32-bit wide argument.Here is the disassembly of provided by lldb:
Using
godbolt.org
I've reconstructed the possible definitioon ofnano_set_uint32
in C language:such that generated assembly by clang 16 with -O2 optimization produces almost the same assembly with the difference in one instruction which I believe effectively does the same thing - 64-bit to 32-bit integer truncation:
There is obviously something wrong here, either
apmpb_copy_measurement_bundle
should allocate larger buffer ornano_set_uint32
should not do 8 bytes write.It also seems that somewhere (silent?) conversion from uint32_t* to uint64_t* done, leading to buffer overflow later.
Could you please inspect related part of Firebase SDK source code and fix buffer overflow problem?
This issue is probably harmful due to smallest
malloc
block allocated on iOS is actually 16 bytes, but this overrun mess with runtime diagnostic tools, in my casemimalloc
with debug checks enabled.Reproducing the issue
Use Firebase SDK in such a way that it uploads data to it's server.
Firebase SDK Version
10.10.0
Xcode Version
14.3.1
Installation Method
Swift Package Manager
Firebase Product(s)
All
Targeted Platforms
iOS
Relevant Log Output
No response
If using Swift Package Manager, the project's Package.resolved
No response
If using CocoaPods, the project's Podfile.lock
No response
The text was updated successfully, but these errors were encountered: