Skip to content

Boundary condition in cbuf #4002

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

Closed
boblemaire opened this issue Dec 20, 2017 · 3 comments
Closed

Boundary condition in cbuf #4002

boblemaire opened this issue Dec 20, 2017 · 3 comments

Comments

@boblemaire
Copy link
Contributor

boblemaire commented Dec 20, 2017

Basic Infos

Hardware

Hardware: NodeMCU 1 (ESP-12E)
Core Version: 2.4.0-rc2

Description

Problem description
While trying to figure out how data is being lost in webserver responses, I went through the code for cbuf. I discovered a boundary condition in the resize function. If you were to issue the function:
cbuf:resize(cbuf.available());
to reduce the size of a buffer to it's current contents, the new cbuf will be the exact size of the current contents, but cbuf logic requires that the buffer always be at least one byte larger than it's current contents.

Settings in IDE

platformio
Module: NodeMCU 1 (ESP-12E)
Flash Size: 4MM
CPU Frequency: 80Mhz
Upload Using: USB

SKETCH
Here is a sequence of calls to cbuf that illustrates the problem with a cbuf(10):

cbuf buf(10);
Serial.printf("\r\nsize=%d, available=%d, room=%d, full=%s\r\n", buf.size(), buf.available(), buf.room(), buf.full() ? "true" : "false");
for (int i=0; i<8; i++){
    Serial.printf("Write one byte, returned write count=%d, cbuf:",buf.write("X",1));
    Serial.printf("size=%d, available=%d, room=%d, full=%s\r\n", buf.size(), buf.available(), buf.room(), buf.full() ? "true" : "false");
}
Serial.printf("Resize=%d, returned size=%d, cbuf:",buf.available(),buf.resize(buf.available()));
    
Serial.printf("size=%d, available=%d, room=%d, full=%s\r\n", buf.size(), buf.available(), buf.room(), buf.full() ? "true" : "false");
for (int i=0; i<8; i++){
    Serial.printf("Write one byte, returned write count=%d, cbuf:",buf.write("X",1));
    Serial.printf("size=%d, available=%d, room=%d, full=%s\r\n", buf.size(), buf.available(), buf.room(), buf.full() ? "true" : "false");
}

Serial OUTPUT

size=10, available=0, room=9, full=false
Write one byte, returned write count=1, cbuf:size=10, available=1, room=8, full=false
Write one byte, returned write count=1, cbuf:size=10, available=2, room=7, full=false
Write one byte, returned write count=1, cbuf:size=10, available=3, room=6, full=false
Write one byte, returned write count=1, cbuf:size=10, available=4, room=5, full=false
Write one byte, returned write count=1, cbuf:size=10, available=5, room=4, full=false
Write one byte, returned write count=1, cbuf:size=10, available=6, room=3, full=false
Write one byte, returned write count=1, cbuf:size=10, available=7, room=2, full=false
Write one byte, returned write count=1, cbuf:size=10, available=8, room=1, full=false
Resize=8, returned size=8, cbuf:size=8, available=8, room=-1, full=false
Write one byte, returned write count=1, cbuf:size=8, available=1, room=6, full=false
Write one byte, returned write count=1, cbuf:size=8, available=2, room=5, full=false
Write one byte, returned write count=1, cbuf:size=8, available=3, room=4, full=false
Write one byte, returned write count=1, cbuf:size=8, available=4, room=3, full=false
Write one byte, returned write count=1, cbuf:size=8, available=5, room=2, full=false
Write one byte, returned write count=1, cbuf:size=8, available=6, room=1, full=false
Write one byte, returned write count=1, cbuf:size=8, available=7, room=0, full=true
Write one byte, returned write count=0, cbuf:size=8, available=7, room=0, full=true

As you can see, seven bytes are lost as a result of this.

The solution is to change cbuf line 40 from:
if((newSize < bytes_available) || (newSize == _size)) {
to:
if((newSize <= bytes_available) || (newSize == _size)) {

I have tried this fix and it seems to work, in that the buffer is not resized. I haven't yet tried this to see if it solves my missing data problem (I have a workaround in place), but thought someone would like to know about this possible problem in what is a widely used core class.

As an afterthought, invoking the resize as cbuf:resize(cbuf.available()+1); would avoid the problem. Of course recoding cbuf to be able to utilize all of it's size would be the best long term solution.

@devyte
Copy link
Collaborator

devyte commented Dec 21, 2017

@boblemaire can you please prepare a PR?

@boblemaire
Copy link
Contributor Author

OK, may take a day or two.

@boblemaire
Copy link
Contributor Author

Submitted PR #4016.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants