]> git.sesse.net Git - fjl/blobdiff - bytesource.c
More issues with overlong returns.
[fjl] / bytesource.c
index 9e46d20ec0fdd8411326f097e38e774399075176..ca260a1f8756ab5924531fd41c0e245176bc4373 100644 (file)
@@ -21,7 +21,7 @@ uint8_t byte_source_read_marker(struct byte_source* src)
 {
        // Refill until we have at least two bytes or EOF.
        while (src->bytes_available < 2) {
-               const unsigned bytes_to_read = BYTESOURCE_CHUNK_SIZE - src->bytes_available;
+               const unsigned bytes_to_read = 2 - src->bytes_available;
                const ssize_t bytes_read =
                        (*src->input_func)(src->userdata,
                                           src->bytes + src->bytes_available,
@@ -44,7 +44,7 @@ uint8_t byte_source_read_marker(struct byte_source* src)
        uint8_t ret = src->bytes[1];
        memmove(src->bytes, src->bytes + 2, src->bytes_available - 2);
        src->bytes_available -= 2;
-
+       
        return ret;
 }
 
@@ -57,12 +57,13 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len)
        while (src->bytes_available == 0 ||
               (src->bytes_available == 1 && src->bytes[0] == MARKER_CHAR)) {
                const unsigned space_left = BYTESOURCE_CHUNK_SIZE - src->bytes_available;
-               const size_t bytes_to_read = (len > space_left ? space_left : len);
+               const unsigned missing_data = len - src->bytes_available;
+               const size_t bytes_to_read = (missing_data > space_left ? space_left : missing_data);
                assert(bytes_to_read <= BYTESOURCE_CHUNK_SIZE);
                const ssize_t bytes_read =
                        (*src->input_func)(src->userdata,
-                                             src->bytes + src->bytes_available,
-                                             bytes_to_read);
+                                          src->bytes + src->bytes_available,
+                                          bytes_to_read);
                assert(bytes_read >= -1);
                assert(bytes_read <= (ssize_t)bytes_to_read);
                
@@ -80,7 +81,7 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len)
 
                src->bytes_available += bytes_read;
        }
-       
+
        // Now unstuff as much as we can. First of all, if there's a 0xFF at the
        // end of the buffer, we don't include it this time; the unstuff function
        // will only give us an error since it can't decide if it's a marker or
@@ -93,45 +94,47 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len)
                end_marker = true;
        }
 
-       int unstuffed_bytes = (*unstuff_choice)(buf, src->bytes, bytes_to_unstuff);
-       assert(unstuffed_bytes != 0);
-       if (unstuffed_bytes > 0) {
-               // Fast path: No markers in the data. We can basically just
-               // return it.
-               if (end_marker) {
-                       src->bytes_available = 1;
-                       src->bytes[0] = 0xff;
-               } else {
-                       src->bytes_available = 0;
-                       src->bytes[0] = 0;
+       // Fast path: No markers in the data, we don't have more data than we
+       // need. We can basically just return it.
+       if (bytes_to_unstuff <= len) {
+               int unstuffed_bytes = (*unstuff_choice)(buf, src->bytes, bytes_to_unstuff);
+               assert(unstuffed_bytes != 0);
+               if (unstuffed_bytes > 0) {
+                       // Fast path: No markers in the data. We can basically just
+                       // return it.
+                       if (end_marker) {
+                               src->bytes_available = 1;
+                               src->bytes[0] = 0xff;
+                       } else {
+                               src->bytes_available = 0;
+                       }
+                       return unstuffed_bytes;
                }
-               return unstuffed_bytes;
        }
 
        // Slow path: There was a marker in the data. Unstuff manually until
        // we hit the marker, then return that.
-       assert(unstuffed_bytes == -1);
        unsigned bytes_read;
        unsigned bytes_written = 0;
-       for (bytes_read = 0; bytes_read < src->bytes_available; ++bytes_read) {
-               buf[bytes_written++] = src->bytes[bytes_read];
+       for (bytes_read = 0; bytes_read < bytes_to_unstuff && bytes_written < len; ++bytes_read) {
                if (src->bytes[bytes_read] != MARKER_CHAR) {
+                       buf[bytes_written++] = src->bytes[bytes_read];
                        continue;
                }
 
                assert(bytes_read < src->bytes_available);
                if (src->bytes[bytes_read + 1] == STUFF_MARKER) {
+                       src->bytes[bytes_written++] = MARKER_CHAR;
+
                        // Skip the stuff byte.
                        ++bytes_read;
-                       continue;
                } else {
                        // OK, this is our marker.
                        break;
-               }       
+               }
        }
 
        memmove(src->bytes, src->bytes + bytes_read, src->bytes_available - bytes_read);
        src->bytes_available -= bytes_read;
-       assert(bytes_written >= 1);
-       return bytes_written - 1;
+       return bytes_written;
 }