Author: rhuijben
Date: Sat Oct 31 13:52:51 2015
New Revision: 1711632

URL: http://svn.apache.org/viewvc?rev=1711632&view=rev
Log:
Tweak the http2 frame buckets to always return frame size errors when
there is less data in the frame than expected. APR_EOF notifies success,
which is not the right way to report missing data.

* buckets/http2_frame_buckets.c
  (serf_http2_unframe_read,
   serf_http2_unframe_read_iovec,
   serf_http2_unpad_read_padsize): Properly handle APR_EOF.
  (serf_http2_unpad_read): When reading more than payload, try to read
    the padding as well, instead of explicitly keeping that for the
    next read.
  (serf_http2_unpad_read_iovec): Properly handle APR_EOF.

Modified:
    serf/trunk/buckets/http2_frame_buckets.c

Modified: serf/trunk/buckets/http2_frame_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1711632&r1=1711631&r2=1711632&view=diff
==============================================================================
--- serf/trunk/buckets/http2_frame_buckets.c (original)
+++ serf/trunk/buckets/http2_frame_buckets.c Sat Oct 31 13:52:51 2015
@@ -227,6 +227,8 @@ serf_http2_unframe_read(serf_bucket_t *b
           if (!SERF_BUCKET_READ_ERROR(status))
             status = APR_EOF;
         }
+      else if (APR_STATUS_IS_EOF(status))
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
     }
 
   return status;
@@ -280,6 +282,8 @@ serf_http2_unframe_read_iovec(serf_bucke
           if (!SERF_BUCKET_READ_ERROR(status))
             status = APR_EOF;
         }
+      else if (APR_STATUS_IS_EOF(status))
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
     }
 
   return status;
@@ -418,6 +422,8 @@ serf_http2_unpad_read_padsize(serf_bucke
 
       ctx->payload_remaining = (apr_size_t)remaining - ctx->pad_length;
     }
+  else if (APR_STATUS_IS_EOF(status))
+    status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
   else if (!status)
     status = APR_EAGAIN;
 
@@ -467,19 +473,37 @@ serf_http2_unpad_read(serf_bucket_t *buc
       *len = 0;
       return status;
     }
-  else if (ctx->payload_remaining == 0)
+  else if (ctx->payload_remaining == 0
+           && ctx->pad_remaining == 0)
     {
       *len = 0;
-      return serf_http2_unpad_read_padding(bucket);
+      return APR_EOF;
     }
 
-  if (requested > ctx->payload_remaining)
-    requested = ctx->payload_remaining;
+
+  if (requested >= ctx->payload_remaining)
+    requested = ctx->payload_remaining + ctx->pad_remaining;
 
   status = serf_bucket_read(ctx->stream, requested, data, len);
   if (! SERF_BUCKET_READ_ERROR(status))
     {
-      ctx->payload_remaining -= *len;
+      if (*len <= ctx->payload_remaining)
+        ctx->payload_remaining -= *len;
+      else
+        {
+          ctx->pad_remaining -= (*len - ctx->payload_remaining);
+          *len = ctx->payload_remaining;
+          ctx->payload_remaining = 0;
+
+          if (ctx->pad_remaining == 0)
+            status = APR_EOF;
+        }
+
+      if (APR_STATUS_IS_EOF(status)
+          && (ctx->pad_remaining != 0 || ctx->payload_remaining != 0))
+        {
+          status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+        }
     }
 
   return status;
@@ -508,6 +532,7 @@ serf_http2_unpad_read_iovec(serf_bucket_
       return serf_http2_unpad_read_padding(bucket);
     }
 
+  /* ### Can we read data and padding in one go? */
   if (requested > ctx->payload_remaining)
     requested = ctx->payload_remaining;
 
@@ -522,6 +547,12 @@ serf_http2_unpad_read_iovec(serf_bucket_
         len += vecs[i].iov_len;
 
       ctx->payload_remaining -= len;
+
+      if (APR_STATUS_IS_EOF(status)
+          && (ctx->pad_remaining != 0 || ctx->payload_remaining != 0))
+        {
+          status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+        }
     }
 
   return status;


Reply via email to