-
Notifications
You must be signed in to change notification settings - Fork 37
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
use-after-free error in Wire library #454
Comments
Great find! This wont just affect Wire, I know SPI has similar logic, and I will have to comb thru the codebase for other similar mistakes. The suggested fix is a great start that fixes the use-after-free, but leads to another runtime error. As pointed out in #439 mbed::I2C does not have a destructor that calls the de-init for wire, none of the mbed objects do. So when the new wire is created, the HAL complains that the module has already been inited (and not deinited) and fails. I am tempted to just add destructors for all the mbed classes that Artemis uses in the Sparkfun branch of mbed, but I fear that this will be to far a departure from the main branch to ever update again later. I may end up putting in a solution as @paulvha has suggested for the OpenLog in sparkfun/OpenLog_Artemis#117. This "breaks" some of the encapsulation of the mbed core, but isn't nearly as large of a change. I will think on this a bit, but I may still try to sneak a fix in to the upcoming v2.2.1. |
Hi @Wenn0101 thanks for looking at this. If you created the destructors could you push them upstream to mbed? It might just be me, but it seems odd that they don't have them. Also while we are on the topic of hardware de-initialization neither UART::~UART, nor UART::end properly de-initialize the UART hardware. #412, and maybe #411, seem to be in this wheelhouse as well. |
Looking at the Mbed issue, they seem to be reluctant to bring in these changes. Because the feature has been missing for so long, many of the targets never implemented the de-init functions for the various drivers. So if they added it in, it would lead to a situation where some of the target support it and other do not. It could be worth worth a try to see if they would though. I think that this will require more thought then a last minute change, so I am not going to try and include this in v2.2.1. |
Hi @Wenn0101, I think I have come up with a shim that allows us to have our cake and eat it too. Firstly make the changes I suggested above: void arduino::MbedI2C::end() {
if (master != NULL) {
delete master;
master = NULL;
}
#ifdef DEVICE_I2CSLAVE
if (slave != NULL) {
delete slave;
slave = NULL;
}
#endif
} At this point, if we compile and run my example from above we get this:
However if we create a new class derived from Arduino_Apollo3/libraries/Wire/src/Wire.h Lines 20 to 22 in 4e24a02
to: namespace arduino {
class myI2C: public mbed::I2C
{
public:
using mbed::I2C::I2C;
virtual ~myI2C(){
i2c_free(&_i2c);
};
};
class MbedI2C : public HardwareI2C
Arduino_Apollo3/libraries/Wire/src/Wire.h Line 55 in 4e24a02
with: myI2C* master;
with this: master = new myI2C((PinName)_sda, (PinName)_scl);
The |
Also add the WireShim to properly shutdown the Wire hardware.
Subject of the issue
use-after-free error in Wire library.
The relevant methods are
Wire.begin
:Arduino_Apollo3/libraries/Wire/src/Wire.cpp
Lines 14 to 19 in 4e24a02
and
Wire.end
:Arduino_Apollo3/libraries/Wire/src/Wire.cpp
Lines 31 to 40 in 4e24a02
With the sequence:
After the call to Wire.end, master is pointing to the location of the deleted
mbed::I2C
object.Your workbench
Steps to reproduce
Example Code
Example Code Output
Trace of I2C Output
First I2C transmission definitely worked:
Possible solution
This code would stop the use-after-free. Maybe more is needed.
The text was updated successfully, but these errors were encountered: