-
Notifications
You must be signed in to change notification settings - Fork 41
fix Invalid JSON desearilaztion beyond buffer end #184
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
Conversation
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.
Pull Request Overview
This PR addresses issue #183 by correcting JSON deserialization beyond the buffer end.
- Updated deserializeJson call for ArduinoJson v6 and non-v6 implementations, passing request->contentLength() as an additional boundary argument.
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.
The fix is not as simple as relying on request->contentLength());
.
What is happening if you run:
curl -v -X POST -H 'Content-Type: application/json' -d '5' -H 'Content-Length: 3' http://127.0.0.1:8080/json2
If you send 1 byte but specify in headers that you are sending 3 then the server will keep on waiting for 2 more bytes. Eventually it will timeout and This is what curl will say:
An edge case in the other direction where you send 5 bytes but claim 3 in the headers will result in 2 bytes being ignored. curl:
where ESP will say
So 555 and not 55555. Expected. So it seems that it works however you have a point. There are two different |
Actually, after further inspection, I take it back. |
I agree! |
Do you want to see how this can be improved ? |
yes, I will update the PR. |
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.
PR looks better! Just a few things to fix.
If you want to go further in code cleanup, like using the index instead of the tmpObject to make it a little more readable, go ahead!
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.
Pull Request Overview
This PR addresses an issue with invalid JSON deserialization beyond the buffer end by improving buffer allocation and JSON parsing logic. Key changes include:
- Adding a new _tempSize member to track allocated buffer size.
- Removing the unused _contentLength variable in the JSON handler.
- Adjusting JSON parsing logic to ensure proper null termination and buffer bounds checking.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
src/WebRequest.cpp | Added _tempSize to the constructor initializer list. |
src/ESPAsyncWebServer.h | Declared _tempSize member to support buffer size tracking. |
src/AsyncJson.h | Removed the unused _contentLength member. |
src/AsyncJson.cpp | Modified JSON parsing and buffer handling logic for safety. |
Comments suppressed due to low confidence (1)
src/AsyncJson.cpp:174
- Since the buffer is allocated with an extra byte (i.e., malloc(total + 1)), consider renaming or updating _tempSize to reflect the actual allocated size to avoid potential off-by-one misunderstandings in future code changes.
request->_tempSize = total; // store the size of allocation we made into _tempSize
What is "the index"? How will it replace |
@mathieucarbou I have responded to your questions. I need some further guidance. |
You can look at the examples in the project. In the end, the code will work both ways, but usually when determining if this is the first time the callback is called, it is done with |
I would rather check the pointer itself as an indication to whether it was allocated rather than use "index" for that. @mathieucarbou would you accept a solution that is based on a struct with the following members
and a size of "sizeof(size_t) + total + 1" ? I think I could do it robustly this way and without adding a new field ("_tempSize") to the request object. |
yes! you can also just have only one uint8_t pointer that you allocate like you said with |
@ayavilevich : I added more comments to this PR and decided ti push a cleanup commit to complete it. |
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.
Pull Request Overview
This PR fixes an issue where JSON deserialization could access memory beyond its buffer end, by removing the redundant _contentLength member and updating type casts and buffer handling in deserialization.
- Removed the _contentLength member from AsyncJson.h
- Updated deserialization casts from (uint8_t *) to (const char *) in AsyncJson.cpp
- Adjusted handleBody logic and enhanced example documentation to illustrate edge cases
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
src/AsyncJson.h | Removed the redundant _contentLength field to streamline content length validation. |
src/AsyncJson.cpp | Updated deserialization casts and buffer handling to prevent memory overruns. |
examples/Json/Json.ino | Added additional Serial output and documented edge cases for JSON payload handling. |
@mathieucarbou Hey, looks fine. I tested it on my end with some test cases and wasn't able to find any issues. Can you merge this? |
merged! I am waiting for the LIbretiny PR to be updated and merged to issue a new release |
fix for #183