Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

fixed an issue in ngx_unescape_uri that it did not convert "plus" (+)…

… to whitespace.
  • Loading branch information...
commit da3557858b0b6124371f646784dd6b04148b25ec 1 parent ad1f6b4
Yichun Zhang authored March 22, 2010
142  src/ngx_http_set_misc_module.c
@@ -12,6 +12,9 @@ typedef enum {
12 12
 } ngx_http_set_misc_distribution_t;
13 13
 
14 14
 
  15
+static void ngx_unescape_uri_patched(u_char **dst, u_char **src,
  16
+        size_t size, ngx_uint_t type);
  17
+
15 18
 static ndk_upstream_list_t *
16 19
 ngx_http_set_misc_get_upstream_list(u_char *data, size_t len);
17 20
 
@@ -146,7 +149,7 @@ ngx_http_set_misc_unescape_uri(ngx_http_request_t *r,
146 149
 
147 150
     src = v->data; dst = p;
148 151
 
149  
-    ngx_unescape_uri(&dst, &src, v->len, NGX_UNESCAPE_URI_COMPONENT);
  152
+    ngx_unescape_uri_patched(&dst, &src, v->len, NGX_UNESCAPE_URI_COMPONENT);
150 153
 
151 154
     if (src != v->data + v->len) {
152 155
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -486,3 +489,140 @@ ngx_http_set_misc_get_upstream_list(u_char *data, size_t len)
486 489
     return NULL;
487 490
 }
488 491
 
  492
+
  493
+/* XXX we also decode '+' to ' ' */
  494
+static void
  495
+ngx_unescape_uri_patched(u_char **dst, u_char **src, size_t size,
  496
+        ngx_uint_t type)
  497
+{
  498
+    u_char  *d, *s, ch, c, decoded;
  499
+    enum {
  500
+        sw_usual = 0,
  501
+        sw_quoted,
  502
+        sw_quoted_second
  503
+    } state;
  504
+
  505
+    d = *dst;
  506
+    s = *src;
  507
+
  508
+    state = 0;
  509
+    decoded = 0;
  510
+
  511
+    while (size--) {
  512
+
  513
+        ch = *s++;
  514
+
  515
+        switch (state) {
  516
+        case sw_usual:
  517
+            if (ch == '?'
  518
+                && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT)))
  519
+            {
  520
+                *d++ = ch;
  521
+                goto done;
  522
+            }
  523
+
  524
+            if (ch == '%') {
  525
+                state = sw_quoted;
  526
+                break;
  527
+            }
  528
+
  529
+            if (ch == '+') {
  530
+                *d++ = ' ';
  531
+                break;
  532
+            }
  533
+
  534
+            *d++ = ch;
  535
+            break;
  536
+
  537
+        case sw_quoted:
  538
+
  539
+            if (ch >= '0' && ch <= '9') {
  540
+                decoded = (u_char) (ch - '0');
  541
+                state = sw_quoted_second;
  542
+                break;
  543
+            }
  544
+
  545
+            c = (u_char) (ch | 0x20);
  546
+            if (c >= 'a' && c <= 'f') {
  547
+                decoded = (u_char) (c - 'a' + 10);
  548
+                state = sw_quoted_second;
  549
+                break;
  550
+            }
  551
+
  552
+            /* the invalid quoted character */
  553
+
  554
+            state = sw_usual;
  555
+
  556
+            *d++ = ch;
  557
+
  558
+            break;
  559
+
  560
+        case sw_quoted_second:
  561
+
  562
+            state = sw_usual;
  563
+
  564
+            if (ch >= '0' && ch <= '9') {
  565
+                ch = (u_char) ((decoded << 4) + ch - '0');
  566
+
  567
+                if (type & NGX_UNESCAPE_REDIRECT) {
  568
+                    if (ch > '%' && ch < 0x7f) {
  569
+                        *d++ = ch;
  570
+                        break;
  571
+                    }
  572
+
  573
+                    *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
  574
+
  575
+                    break;
  576
+                }
  577
+
  578
+                *d++ = ch;
  579
+
  580
+                break;
  581
+            }
  582
+
  583
+            c = (u_char) (ch | 0x20);
  584
+            if (c >= 'a' && c <= 'f') {
  585
+                ch = (u_char) ((decoded << 4) + c - 'a' + 10);
  586
+
  587
+                if (type & NGX_UNESCAPE_URI) {
  588
+                    if (ch == '?') {
  589
+                        *d++ = ch;
  590
+                        goto done;
  591
+                    }
  592
+
  593
+                    *d++ = ch;
  594
+                    break;
  595
+                }
  596
+
  597
+                if (type & NGX_UNESCAPE_REDIRECT) {
  598
+                    if (ch == '?') {
  599
+                        *d++ = ch;
  600
+                        goto done;
  601
+                    }
  602
+
  603
+                    if (ch > '%' && ch < 0x7f) {
  604
+                        *d++ = ch;
  605
+                        break;
  606
+                    }
  607
+
  608
+                    *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
  609
+                    break;
  610
+                }
  611
+
  612
+                *d++ = ch;
  613
+
  614
+                break;
  615
+            }
  616
+
  617
+            /* the invalid quoted character */
  618
+
  619
+            break;
  620
+        }
  621
+    }
  622
+
  623
+done:
  624
+
  625
+    *dst = d;
  626
+    *src = s;
  627
+}
  628
+
16  test/t/sanity.t
@@ -3,7 +3,7 @@
3 3
 use lib 'lib';
4 4
 use Test::Nginx::Socket;
5 5
 
6  
-repeat_each(3);
  6
+#repeat_each(3);
7 7
 
8 8
 plan tests => repeat_each() * 2 * blocks();
9 9
 
@@ -225,3 +225,17 @@ GET /foo
225 225
 --- response_body
226 226
 null
227 227
 
  228
+
  229
+
  230
+=== TEST 13: unescape '+' to ' '
  231
+--- config
  232
+    location /bar {
  233
+        set $a 'a+b';
  234
+        set_unescape_uri $a;
  235
+        echo $a;
  236
+    }
  237
+--- request
  238
+    GET /bar
  239
+--- response_body
  240
+a b
  241
+

0 notes on commit da35578

Please sign in to comment.
Something went wrong with that request. Please try again.