Появляются лишние символы при использовании SSI echo.

Maxim Dounin mdounin at mdounin.ru
Thu Feb 19 03:48:40 MSK 2009


Hello!

On Wed, Feb 18, 2009 at 06:20:52AM +0300, Maxim Dounin wrote:

> Hello!
> 
> On Tue, Feb 17, 2009 at 09:39:55PM +0500, Владислав Щапов wrote:
> 
> > Здравствуйте.
> > 
> > Отловил Debug-log на nginx 0.7.34. На версии 0.7.35 баг не исчез, НО стал
> > проявляться значительно реже.
> > Проблема возникает в файле /static/XXXXXXXX_menu.html?menu_account=selected
> > (Х-ами заменено реальное название но количество символов сохранено. Такие-же
> > замены сделаны и в логах)
> > Результат вывода echo такой "<li class="tab3 selected/rpc">" хотя в этом
> > месте явно должен был быть код '<li class="tab3  selected">'. При следующем
> > запросе вывелось "<li class="tab3 selectedml" &gt;="">", потом "<li
> > class="tab3
> > selectedq��">".

[...]

> Патч нарисую завтра если Игорь не успеет раньше.

Патч прилагается.

Maxim Dounin

> 
> To Игорь:
> 
> В функции ngx_http_arg() утверждение
> 
>         /*
>          * although r->args.data is not null-terminated by itself,
>          * however, there is null in the end of request line
>          */
> 
> не является правдой для подзапросов из ssi.
> 
> Maxim Dounin
> 
> > 
> > Так-же в конце лога подозрительно выглядят строчки "2009/02/17 21:01:23
> > [debug] 5669#0: *2280 free: 00000000"
> > 
> > 16 февраля 2009 г. 18:22 пользователь Владислав Щапов <phprus at gmail.com>написал:
> > 
> > > Здравствуйте.
> > > Nginx и так был собран с --with-debug.
> > > Жаль, что дебаг лог я вчера включить не догадался. Сегодня при помощи ab
> > > сделал более 10к запросов к различным страничкам и в том числе к проблемным,
> > > но все запросы окончились успешно, те размеры отдаваемых страниц были точно
> > > такие какие должны были быть, да и ручное кликание по ссылкам результата не
> > > дало. Буду продолжать попытки воспроизвести баг.
> > >
> > > Кусок HTML'я в котором выводятся некорректное значение вот такой:
> > >
> > > <!--# if expr="$account" -->
> > >     <li class="tab3  <!--# echo var="arg_menu_account" default="" -->">
> > >         <a href="/account/">Мой аккаунт</a>
> > >         <ul class="submenu tab_cnt_2">
> > >             <li><a href="/account/">Мой аккаунт</a></li>
> > >             <li><a href="/account/EditPasswd">Изменить email и
> > > пароль</a></li>
> > >             <!-- <li><a href="/account/Setting">Настройки</a></li> -->
> > >         </ul>
> > >     </li>
> > > <!--# endif -->
> > >
> > > Ожидается, что на месте <!--# echo var="arg_menu_account" default="" -->
> > > выведется selected, но выводилось следующее: "selected85;", "selectedml?m" а
> > > так-же другие символы(в том числе и не алфавитно-цифровые) которых я не
> > > помню.
> > >
> > > nginx скомпилирован таким образом:
> > > ./configure --prefix=/usr/local/nginx \
> > >             --error-log-path=/var/log/nginx/error.log \
> > >             --http-log-path=/var/log/nginx/access.log \
> > >             --http-client-body-temp-path=/var/spool/nginx/client_body_temp
> > > \
> > >             --http-proxy-temp-path=/var/spool/nginx/proxy_temp \
> > >             --http-fastcgi-temp-path=/var/spool/nginx/fastcgi_temp \
> > >             --pid-path=/var/run/nginx/nginx.pid \
> > >             --with-http_ssl_module \
> > >             --with-http_sub_module \
> > >             --with-http_gzip_static_module \
> > >             --with-http_addition_module \
> > >             --with-http_flv_module \
> > >             --with-http_xslt_module \
> > >             --with-http_secure_link_module \
> > >             --with-http_dav_module \
> > >             --with-debug
> > >
> > >
> > > 16 февраля 2009 г. 1:56 пользователь Maxim Dounin <mdounin at mdounin.ru>написал:
> > >
> > > Hello!
> > >>
> > >> On Sun, Feb 15, 2009 at 11:10:11PM +0500, Владислав Щапов wrote:
> > >>
> > >> > Накаркал. Сейчас эти лишние символы стали появляться буквально через
> > >> раз, но
> > >> > зато удалось заметить, что их либо 3 либо 4 штуки. :(
> > >> >
> > >> > Кстати забыл еще упомянуть такую деталь, что этот echo находится внутри
> > >> if'а
> > >> > который проверяет существование другой переменной, которая
> > >> устанавливается
> > >> > или не устанавливается в подключаемой внешним файлом при помощи include
> > >> (с
> > >> > указанием параметра wait="yes") html-странице.
> > >>
> > >> Постарайтесь сделать debug log для запроса, на котором проявляется
> > >> проблема.  Для этого надо собрать nginx с параметром configure
> > >> --with-debug.  Логгирование с уровнем debug можно включить для
> > >> конкретных ip-адресов так:
> > >>
> > >> events {
> > >>    ...
> > >>    debug_connection  127.0.0.1;
> > >>    debug_connection  192.168.0.0/16;
> > >> }
> > >>
> > >> Имея debug log можно будет пытаться что-то понять (также
> > >> желательно полный исходный код ssi-страницы, и результат запроса с
> > >> видимой проблемой).
> > >>
> > >> Maxim Dounin
> > >>
> > >> >
> > >> > 15 февраля 2009 г. 18:49 пользователь Владислав Щапов <phprus at gmail.com
> > >> >написал:
> > >> >
> > >> > > Здравствуйте.
> > >> > > Есть nginx 0.7.34
> > >> > > Столкнулся с тем, что при использовании конструкции <!--# echo
> > >> > > var="arg_menu_account" default="" --> после самого значения параметра
> > >> иногда
> > >> > > выводятся несколько левых символов (два раза выводились 3 лишних
> > >> символа,
> > >> > > один раз 4). Параметр menu_account в строке запроса имеет значение
> > >> selected.
> > >> > > Специально воспроизвести эту проблему не получилось.
> > >> > >
> > >> > > Подскажите пожалуйста, в чем может быть причина такого странного
> > >> поведения
> > >> > > Nginx?
> > >> > >
> > >>
> > >>
> > >
> 
> 
> 
-------------- next part --------------
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1235004189 -10800
# Node ID 1e08c822aec3628f1b009ffc485635db2b03262d
# Parent  40964c811e5907ad2901ddddda8ea505f2fef9d4
Http core: fix ngx_http_arg() to work with ssi subrequests.

There is no request line for subrequests, and hence it's incorrect to assume
there will be NUL somewhere after args.

diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -692,6 +692,33 @@ ngx_strcasestrn(u_char *s1, char *s2, si
 }
 
 
+u_char *
+ngx_strlcasestrn(u_char *s1, u_char *last, u_char *s2, size_t n)
+{
+    ngx_uint_t  c1, c2;
+
+    c2 = (ngx_uint_t) *s2++;
+    c2  = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
+    last -= n;
+
+    do {
+        do {
+            if (s1 == last) {
+                return NULL;
+            }
+
+            c1 = (ngx_uint_t) *s1++;
+
+            c1  = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
+
+        } while (c1 != c2);
+
+    } while (ngx_strncasecmp(s1, s2, n) != 0);
+
+    return --s1;
+}
+
+
 ngx_int_t
 ngx_rstrncmp(u_char *s1, u_char *s2, size_t n)
 {
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -149,6 +149,7 @@ u_char *ngx_strnstr(u_char *s1, char *s2
 
 u_char *ngx_strstrn(u_char *s1, char *s2, size_t n);
 u_char *ngx_strcasestrn(u_char *s1, char *s2, size_t n);
+u_char *ngx_strlcasestrn(u_char *s1, u_char *last, u_char *s2, size_t n);
 
 ngx_int_t ngx_rstrncmp(u_char *s1, u_char *s2, size_t n);
 ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n);
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -1486,20 +1486,20 @@ ngx_http_parse_multi_header_lines(ngx_ar
 ngx_int_t
 ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)
 {
-    u_char  *p;
+    u_char  *p, *last;
 
     if (r->args.len == 0) {
         return NGX_DECLINED;
     }
 
-    for (p = r->args.data; *p && *p != ' '; p++) {
+    p = r->args.data;
+    last = p + r->args.len;
 
-        /*
-         * although r->args.data is not null-terminated by itself,
-         * however, there is null in the end of request line
-         */
+    for ( /* void */ ; p < last; p++) {
 
-        p = ngx_strcasestrn(p, (char *) name, len - 1);
+        /* we need '=' after name, so drop one char from last */
+
+        p = ngx_strlcasestrn(p, last - 1, name, len - 1);
 
         if (p == NULL) {
             return NGX_DECLINED;
@@ -1509,7 +1509,7 @@ ngx_http_arg(ngx_http_request_t *r, u_ch
 
             value->data = p + len + 1;
 
-            p = (u_char *) ngx_strchr(p, '&');
+            p = ngx_strlchr(p, last, '&');
 
             if (p == NULL) {
                 p = r->args.data + r->args.len;


More information about the nginx-ru mailing list