Mercurial > hg > nginx
comparison src/http/modules/ngx_http_mp4_module.c @ 6782:b123eae3fd4e
Mp4: introduced custom version of ngx_atofp().
This allows to correctly parse "start" and "end" arguments without
null-termination (ticket #475), and also fixes rounding errors observed
with strtod() when using i387 instructions.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 27 Oct 2016 17:57:16 +0300 |
parents | 6136a51f9c21 |
children | 2b2239a1e0d4 |
comparison
equal
deleted
inserted
replaced
6781:ca27074f8f0f | 6782:b123eae3fd4e |
---|---|
214 #define ngx_mp4_last_trak(mp4) \ | 214 #define ngx_mp4_last_trak(mp4) \ |
215 &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1] | 215 &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1] |
216 | 216 |
217 | 217 |
218 static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r); | 218 static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r); |
219 static ngx_int_t ngx_http_mp4_atofp(u_char *line, size_t n, size_t point); | |
219 | 220 |
220 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); | 221 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); |
221 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, | 222 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, |
222 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); | 223 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); |
223 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size); | 224 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size); |
535 | 536 |
536 if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { | 537 if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { |
537 | 538 |
538 /* | 539 /* |
539 * A Flash player may send start value with a lot of digits | 540 * A Flash player may send start value with a lot of digits |
540 * after dot so strtod() is used instead of atofp(). NaNs and | 541 * after dot so a custom function is used instead of ngx_atofp(). |
541 * infinities become negative numbers after (int) conversion. | |
542 */ | 542 */ |
543 | 543 |
544 ngx_set_errno(0); | 544 start = ngx_http_mp4_atofp(value.data, value.len, 3); |
545 start = (int) (strtod((char *) value.data, NULL) * 1000); | |
546 | |
547 if (ngx_errno != 0) { | |
548 start = -1; | |
549 } | |
550 } | 545 } |
551 | 546 |
552 if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) { | 547 if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) { |
553 | 548 |
554 ngx_set_errno(0); | 549 end = ngx_http_mp4_atofp(value.data, value.len, 3); |
555 end = (int) (strtod((char *) value.data, NULL) * 1000); | |
556 | |
557 if (ngx_errno != 0) { | |
558 end = -1; | |
559 } | |
560 | 550 |
561 if (end > 0) { | 551 if (end > 0) { |
562 if (start < 0) { | 552 if (start < 0) { |
563 start = 0; | 553 start = 0; |
564 } | 554 } |
681 | 671 |
682 out.buf = b; | 672 out.buf = b; |
683 out.next = NULL; | 673 out.next = NULL; |
684 | 674 |
685 return ngx_http_output_filter(r, &out); | 675 return ngx_http_output_filter(r, &out); |
676 } | |
677 | |
678 | |
679 static ngx_int_t | |
680 ngx_http_mp4_atofp(u_char *line, size_t n, size_t point) | |
681 { | |
682 ngx_int_t value, cutoff, cutlim; | |
683 ngx_uint_t dot; | |
684 | |
685 /* same as ngx_atofp(), but allows additional digits */ | |
686 | |
687 if (n == 0) { | |
688 return NGX_ERROR; | |
689 } | |
690 | |
691 cutoff = NGX_MAX_INT_T_VALUE / 10; | |
692 cutlim = NGX_MAX_INT_T_VALUE % 10; | |
693 | |
694 dot = 0; | |
695 | |
696 for (value = 0; n--; line++) { | |
697 | |
698 if (*line == '.') { | |
699 if (dot) { | |
700 return NGX_ERROR; | |
701 } | |
702 | |
703 dot = 1; | |
704 continue; | |
705 } | |
706 | |
707 if (*line < '0' || *line > '9') { | |
708 return NGX_ERROR; | |
709 } | |
710 | |
711 if (point == 0) { | |
712 continue; | |
713 } | |
714 | |
715 if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) { | |
716 return NGX_ERROR; | |
717 } | |
718 | |
719 value = value * 10 + (*line - '0'); | |
720 point -= dot; | |
721 } | |
722 | |
723 while (point--) { | |
724 if (value > cutoff) { | |
725 return NGX_ERROR; | |
726 } | |
727 | |
728 value = value * 10; | |
729 } | |
730 | |
731 return value; | |
686 } | 732 } |
687 | 733 |
688 | 734 |
689 static ngx_int_t | 735 static ngx_int_t |
690 ngx_http_mp4_process(ngx_http_mp4_file_t *mp4) | 736 ngx_http_mp4_process(ngx_http_mp4_file_t *mp4) |