comparison src/http/ngx_http_variables.c @ 8164:b71e69247483

Variables: avoid possible buffer overrun with some "$sent_http_*". The existing logic to evaluate multi header "$sent_http_*" variables, such as $sent_http_cache_control, as previously introduced in 1.23.0, doesn't take into account that one or more elements can be cleared, yet still present in a linked list, pointed to by the next field. Such elements don't contribute to the resulting variable length, an attempt to append a separator for them ends up in out of bounds write. This is not possible with standard modules, though at least one third party module is known to override multi header values this way, so it makes sense to harden the logic. The fix restores a generic boundary check.
author Sergey Kandaurov <pluknet@nginx.com>
date Mon, 01 May 2023 19:16:05 +0400
parents cca4c8a715de
children 106b3832e7ef
comparison
equal deleted inserted replaced
8163:77d5c662f3d9 8164:b71e69247483
826 static ngx_int_t 826 static ngx_int_t
827 ngx_http_variable_headers_internal(ngx_http_request_t *r, 827 ngx_http_variable_headers_internal(ngx_http_request_t *r,
828 ngx_http_variable_value_t *v, uintptr_t data, u_char sep) 828 ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
829 { 829 {
830 size_t len; 830 size_t len;
831 u_char *p; 831 u_char *p, *end;
832 ngx_table_elt_t *h, *th; 832 ngx_table_elt_t *h, *th;
833 833
834 h = *(ngx_table_elt_t **) ((char *) r + data); 834 h = *(ngx_table_elt_t **) ((char *) r + data);
835 835
836 len = 0; 836 len = 0;
868 } 868 }
869 869
870 v->len = len; 870 v->len = len;
871 v->data = p; 871 v->data = p;
872 872
873 end = p + len;
874
873 for (th = h; th; th = th->next) { 875 for (th = h; th; th = th->next) {
874 876
875 if (th->hash == 0) { 877 if (th->hash == 0) {
876 continue; 878 continue;
877 } 879 }
878 880
879 p = ngx_copy(p, th->value.data, th->value.len); 881 p = ngx_copy(p, th->value.data, th->value.len);
880 882
881 if (th->next == NULL) { 883 if (p == end) {
882 break; 884 break;
883 } 885 }
884 886
885 *p++ = sep; *p++ = ' '; 887 *p++ = sep; *p++ = ' ';
886 } 888 }