-
Notifications
You must be signed in to change notification settings - Fork 51
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
Gracefully handle type confusion of inflate_state and tdefl_compressor in mz_stream in C API #36
Conversation
…type confusion caused by C API
Hi, I'm not sure that this is right either. If there is a type confusion and |
@Frommi you are right. I should put |
So, I thought about it more, ran valgrind and there are some thoughts:
I think a better idea is to have some kind of |
I didn't notice that Thanks for the detailed investigation. I have the same concern when writing a fix. I tried to use a field to indicate the type of a |
About initialization, I meant that if after alloc About |
I tried this, but it needs major modifications:
|
I came back, looked at the code and I think the best place to put a check is in the P.S. Better yet, put |
How do I compare a field with the type parameter Say I have a enum:
|
One way to do it is add a method But I really think that having |
Hi @Frommi, I think this is a working PR. There are two questions still need to solve:
|
Hi, It's okay and is logically right to not do the check in I see that you use In |
Thanks for you feedback. Let me try to change the code accordingly. |
@Frommi I tried to implement in the other way. Because I'm not familiar with different types/structs, it is difficult for me to finish it. |
Okay, I'll implement it and push it here. Another question is should we free the struct by it's real type in case of type confusion or only return error code? If not, there will be memory leak, which is probably fine, and the other way we risk something like double free. Do you have an opinion on this and do you know what zlib does? |
For int mz_inflateEnd(mz_streamp pStream)
{
if (!pStream)
return MZ_STREAM_ERROR;
if (pStream->state)
{
pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL;
}
return MZ_OK;
}
int mz_deflateEnd(mz_streamp pStream)
{
if (!pStream)
return MZ_STREAM_ERROR;
if (pStream->state)
{
pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL;
}
return MZ_OK;
} https://github.com/richgel999/miniz/blob/master/miniz.c |
Any update on this PR? |
Hi I've looked over the changes. I am a little unsure about this Is it okay to cast an unknown pointer as a trait object like that? I haven't really used dynamic dispatch in Rust much. |
@oyvindln what did you mean? |
Ah I misread the code a bit. It's not a trait object. Though the state field in mz_stream is of type pointer to mz_internal_state (which is an empty struct), so I'm not sure if reading it as if it's a statetype is correct. Might be better to put the StreamType field somewhere the mz_stream type. Sorry for the late reply. |
Hi, @oyvindln . Do you have any better suggestion? Thanks. |
Hi, is it possible to merge this PR or can we discuss how to improve the fix? Thanks. |
Hi, sorry for taking so long to reply. |
Double free can actually be exploitable, so please prioritize fixing this. This is all the more critical because miniz_oxide is used in |
Resolved this in #49 |
The
inflate_state
andtdefl_compressor
state struct are not consistent. This will cause a type confusion issue when callingdeflateEnd
with the inflate stream buffer using the C API, resulting a "double free" crash. The zlib library doesn't have this problem because when calling thedeflateEnd
, it knows the type of the state buffer. Instead, miniz_oxide's C API has to cast this buffer to Rust's type and lose its original type.This PR crates a bogus field to make the
inflate_state
strut same astdefl_compressor
to work around this memory safety issue.