[nginx] SPDY: improved error handling of header block decompress...

Valentin Bartenev vbart at nginx.com
Thu May 15 15:25:48 UTC 2014


details:   http://hg.nginx.org/nginx/rev/fb56f5d612a0
branches:  
changeset: 5690:fb56f5d612a0
user:      Valentin Bartenev <vbart at nginx.com>
date:      Wed Apr 30 20:34:20 2014 +0400
description:
SPDY: improved error handling of header block decompression.

Now cases when decompression failed due to internal error
and when a client sent corrupted data are distinguished.

diffstat:

 src/http/ngx_http_spdy.c |  62 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 44 insertions(+), 18 deletions(-)

diffs (117 lines):

diff -r 5d55f03b1e12 -r fb56f5d612a0 src/http/ngx_http_spdy.c
--- a/src/http/ngx_http_spdy.c	Wed Apr 30 20:34:20 2014 +0400
+++ b/src/http/ngx_http_spdy.c	Wed Apr 30 20:34:20 2014 +0400
@@ -123,6 +123,9 @@ static u_char *ngx_http_spdy_state_compl
     u_char *pos, u_char *end);
 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
     u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler);
+
+static u_char *ngx_http_spdy_state_inflate_error(
+    ngx_http_spdy_connection_t *sc, int rc);
 static u_char *ngx_http_spdy_state_protocol_error(
     ngx_http_spdy_connection_t *sc);
 static u_char *ngx_http_spdy_state_internal_error(
@@ -1036,11 +1039,21 @@ ngx_http_spdy_state_headers(ngx_http_spd
     if (z == Z_NEED_DICT) {
         z = inflateSetDictionary(&sc->zstream_in, ngx_http_spdy_dict,
                                  sizeof(ngx_http_spdy_dict));
+
         if (z != Z_OK) {
-            ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-                          "spdy inflateSetDictionary() failed: %d", z);
-
-            return ngx_http_spdy_state_protocol_error(sc);
+            if (z == Z_DATA_ERROR) {
+                ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+                              "client sent SYN_STREAM frame with header "
+                              "block encoded using wrong dictionary: %ul",
+                              (u_long) sc->zstream_in.adler);
+
+                return ngx_http_spdy_state_protocol_error(sc);
+            }
+
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "inflateSetDictionary() failed: %d", z);
+
+            return ngx_http_spdy_state_internal_error(sc);
         }
 
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1051,10 +1064,7 @@ ngx_http_spdy_state_headers(ngx_http_spd
     }
 
     if (z != Z_OK) {
-        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-                      "spdy inflate() failed: %d", z);
-
-        return ngx_http_spdy_state_protocol_error(sc);
+        return ngx_http_spdy_state_inflate_error(sc, z);
     }
 
     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1155,10 +1165,7 @@ ngx_http_spdy_state_headers(ngx_http_spd
                 z = inflate(&sc->zstream_in, Z_NO_FLUSH);
 
                 if (z != Z_OK) {
-                    ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-                                  "spdy inflate() failed: %d", z);
-
-                    return ngx_http_spdy_state_protocol_error(sc);
+                    return ngx_http_spdy_state_inflate_error(sc, z);
                 }
 
                 sc->length -= sc->zstream_in.next_in - pos;
@@ -1268,12 +1275,8 @@ ngx_http_spdy_state_headers_skip(ngx_htt
 
         n = inflate(&sc->zstream_in, Z_NO_FLUSH);
 
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
-                       "spdy inflate(): %d", n);
-
         if (n != Z_OK) {
-            /* TODO: logging */
-            return ngx_http_spdy_state_protocol_error(sc);
+            return ngx_http_spdy_state_inflate_error(sc, n);
         }
     }
 
@@ -1912,6 +1915,24 @@ ngx_http_spdy_state_save(ngx_http_spdy_c
 
 
 static u_char *
+ngx_http_spdy_state_inflate_error(ngx_http_spdy_connection_t *sc, int rc)
+{
+    if (rc == Z_DATA_ERROR || rc == Z_STREAM_END) {
+        ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
+                      "client sent SYN_STREAM frame with "
+                      "corrupted header block, inflate() failed: %d", rc);
+
+        return ngx_http_spdy_state_protocol_error(sc);
+    }
+
+    ngx_log_error(NGX_LOG_ERR, sc->connection->log, 0,
+                  "inflate() failed: %d", rc);
+
+    return ngx_http_spdy_state_internal_error(sc);
+}
+
+
+static u_char *
 ngx_http_spdy_state_protocol_error(ngx_http_spdy_connection_t *sc)
 {
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
@@ -1934,8 +1955,13 @@ ngx_http_spdy_state_internal_error(ngx_h
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
                    "spdy state internal error");
 
-    /* TODO */
+    if (sc->stream) {
+        sc->stream->out_closed = 1;
+        ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
+    }
+
     ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR);
+
     return NULL;
 }
 



More information about the nginx-devel mailing list