Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Change
Add ObjC.ProxyBlock.
Use stackblock instead of globalblock to solve the strange crash encountered in the process of replacing block implementation.
Adjust blockDescriptorAllocSize and blockDescriptorOffsets to fit ProxyBlock's 3part-Descriptor, and keep offset.rest for Original ObjC.block.
Change descriptor->size from blockDescriptorDeclaredSize to blockSize.
Problems
Haven't written a test case yet.
If the script is disposed, the application may crash.
(ObjC.block have the same problem?)
Reason
blockDescriptorDeclaredSize and blockSize
When Block_copy is used on stackblcok, descriptor->size is used to request memory to store "another part".So size should be block's size.(But have no effect on GlobalBlock)
ProxyBlock
The globleblock has some difficulties in solving life cycle problems. For example:
-[NSURLSession dataTaskWithURL:completionHandler:], send a network request and process the response in a callback. Now you want to know which request created the response.
Solution 1 Try the example provided in the documentation:
It looks good, but what happens if each incoming block is the same? For example, a developer is only concerned about whether a network request is in error and receives a response with a globalblock.
Solution 2
Create a new block to replace the old one. And call the old one in the new block. Work like ObjC.Proxy.
It looks good, doesn't it? Each request received a different callback. Just release the callback at the right time. No, not that simple.
What is the difference between pendingBlocks.delete in the first two examples? Why need 'setTimeout'?
The problem is that the callback "holder" does not necessarily release the callback immediately after the callback has been executed, and we don't know when the release will occur by current implementation.(Unless we monitor the call of _Block_relase and judge whether this parameter is a callback generated by frida, ah,and we have to maintain retain count ourselves)
For most cases, setTimeout400 is enough, but some applications will crash unless setTimeout is set to more than ten seconds. One possibility I can think of is that the callback will be released when an autorelease pool is released, so there are differences between different applications.
In summary, it might be a good idea to use a stackblock and wait for the lifecycle call(copy/dispose helper) of the OC.