comparison src/http/modules/ngx_http_mp4_module.c @ 670:ad45b044f1e5 NGINX_1_1_19

nginx 1.1.19 *) Security: specially crafted mp4 file might allow to overwrite memory locations in a worker process if the ngx_http_mp4_module was used, potentially resulting in arbitrary code execution (CVE-2012-2089). Thanks to Matthew Daley. *) Bugfix: nginx/Windows might be terminated abnormally. Thanks to Vincent Lee. *) Bugfix: nginx hogged CPU if all servers in an upstream were marked as "backup". *) Bugfix: the "allow" and "deny" directives might be inherited incorrectly if they were used with IPv6 addresses. *) Bugfix: the "modern_browser" and "ancient_browser" directives might be inherited incorrectly. *) Bugfix: timeouts might be handled incorrectly on Solaris/SPARC. *) Bugfix: in the ngx_http_mp4_module.
author Igor Sysoev <http://sysoev.ru>
date Thu, 12 Apr 2012 00:00:00 +0400
parents f5b859b2f097
children 4dcaf40cc702
comparison
equal deleted inserted replaced
669:3f5d0be5ee74 670:ad45b044f1e5
154 } ngx_http_mp4_atom_handler_t; 154 } ngx_http_mp4_atom_handler_t;
155 155
156 156
157 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) 157 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8)
158 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos 158 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos
159 #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8)
159 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n 160 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n
160 161
161 162
162 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ 163 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \
163 ((u_char *) (p))[4] = n1; \ 164 ((u_char *) (p))[4] = n1; \
202 203
203 204
204 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); 205 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
205 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, 206 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
206 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); 207 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size);
207 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4); 208 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size);
208 static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, 209 static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4,
209 uint64_t atom_data_size); 210 uint64_t atom_data_size);
210 static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, 211 static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
211 uint64_t atom_data_size); 212 uint64_t atom_data_size);
212 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, 213 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
263 uint64_t atom_data_size); 264 uint64_t atom_data_size);
264 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, 265 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
265 ngx_http_mp4_trak_t *trak); 266 ngx_http_mp4_trak_t *trak);
266 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, 267 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
267 uint64_t atom_data_size); 268 uint64_t atom_data_size);
268 static void ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, 269 static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
269 ngx_http_mp4_trak_t *trak); 270 ngx_http_mp4_trak_t *trak);
270 static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, 271 static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4,
271 uint64_t atom_data_size); 272 uint64_t atom_data_size);
272 static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4, 273 static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
273 ngx_http_mp4_trak_t *trak); 274 ngx_http_mp4_trak_t *trak);
699 700
700 if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) { 701 if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) {
701 return NGX_ERROR; 702 return NGX_ERROR;
702 } 703 }
703 704
704 ngx_http_mp4_update_stsz_atom(mp4, &trak[i]); 705 if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) {
706 return NGX_ERROR;
707 }
705 708
706 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { 709 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
707 if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) { 710 if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) {
708 return NGX_ERROR; 711 return NGX_ERROR;
709 } 712 }
750 adjustment = mp4->ftyp_size + mp4->moov_size 753 adjustment = mp4->ftyp_size + mp4->moov_size
751 + ngx_http_mp4_update_mdat_atom(mp4, start_offset) 754 + ngx_http_mp4_update_mdat_atom(mp4, start_offset)
752 - start_offset; 755 - start_offset;
753 756
754 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 757 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
755 "mp4 adjustment:%D", adjustment); 758 "mp4 adjustment:%O", adjustment);
756 759
757 for (i = 0; i < mp4->trak.nelts; i++) { 760 for (i = 0; i < mp4->trak.nelts; i++) {
758 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { 761 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
759 ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment); 762 ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment);
760 } else { 763 } else {
791 794
792 end = mp4->offset + atom_data_size; 795 end = mp4->offset + atom_data_size;
793 796
794 while (mp4->offset < end) { 797 while (mp4->offset < end) {
795 798
796 if (mp4->buffer_pos + sizeof(uint32_t) > mp4->buffer_end) { 799 if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) {
797 if (ngx_http_mp4_read(mp4) != NGX_OK) { 800 return NGX_ERROR;
798 return NGX_ERROR;
799 }
800 } 801 }
801 802
802 atom_header = mp4->buffer_pos; 803 atom_header = mp4->buffer_pos;
803 atom_size = ngx_mp4_get_32value(atom_header); 804 atom_size = ngx_mp4_get_32value(atom_header);
804 atom_header_size = sizeof(ngx_mp4_atom_header_t); 805 atom_header_size = sizeof(ngx_mp4_atom_header_t);
811 812
812 if (atom_size < sizeof(ngx_mp4_atom_header_t)) { 813 if (atom_size < sizeof(ngx_mp4_atom_header_t)) {
813 814
814 if (atom_size == 1) { 815 if (atom_size == 1) {
815 816
816 if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header64_t) 817 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t))
817 > mp4->buffer_end) 818 != NGX_OK)
818 { 819 {
819 if (ngx_http_mp4_read(mp4) != NGX_OK) { 820 return NGX_ERROR;
820 return NGX_ERROR;
821 }
822
823 atom_header = mp4->buffer_pos;
824 } 821 }
825 822
826 /* 64-bit atom size */ 823 /* 64-bit atom size */
824 atom_header = mp4->buffer_pos;
827 atom_size = ngx_mp4_get_64value(atom_header + 8); 825 atom_size = ngx_mp4_get_64value(atom_header + 8);
828 atom_header_size = sizeof(ngx_mp4_atom_header64_t); 826 atom_header_size = sizeof(ngx_mp4_atom_header64_t);
829 827
830 } else { 828 } else {
831 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 829 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
833 mp4->file.name.data, atom_size); 831 mp4->file.name.data, atom_size);
834 return NGX_ERROR; 832 return NGX_ERROR;
835 } 833 }
836 } 834 }
837 835
838 if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header_t) > mp4->buffer_end) { 836 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) {
839 if (ngx_http_mp4_read(mp4) != NGX_OK) { 837 return NGX_ERROR;
840 return NGX_ERROR; 838 }
841 } 839
842 840 atom_header = mp4->buffer_pos;
843 atom_header = mp4->buffer_pos;
844 }
845
846 atom_name = atom_header + sizeof(uint32_t); 841 atom_name = atom_header + sizeof(uint32_t);
847 842
848 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 843 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
849 "mp4 atom: %*s @%O:%uL", 844 "mp4 atom: %*s @%O:%uL",
850 4, atom_name, mp4->offset, atom_size); 845 4, atom_name, mp4->offset, atom_size);
846
847 if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset)
848 || mp4->offset + (off_t) atom_size > end)
849 {
850 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
851 "\"%s\" mp4 atom too large:%uL",
852 mp4->file.name.data, atom_size);
853 return NGX_ERROR;
854 }
851 855
852 for (n = 0; atom[n].name; n++) { 856 for (n = 0; atom[n].name; n++) {
853 857
854 if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) { 858 if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) {
855 859
873 return NGX_OK; 877 return NGX_OK;
874 } 878 }
875 879
876 880
877 static ngx_int_t 881 static ngx_int_t
878 ngx_http_mp4_read(ngx_http_mp4_file_t *mp4) 882 ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size)
879 { 883 {
880 ngx_int_t n; 884 ssize_t n;
885
886 if (mp4->buffer_pos + size <= mp4->buffer_end) {
887 return NGX_OK;
888 }
881 889
882 if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) { 890 if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) {
883 mp4->buffer_size = (size_t) (mp4->end - mp4->offset); 891 mp4->buffer_size = (size_t) (mp4->end - mp4->offset);
892 }
893
894 if (mp4->buffer_size < size) {
895 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
896 "\"%s\" mp4 file truncated", mp4->file.name.data);
897 return NGX_ERROR;
884 } 898 }
885 899
886 if (mp4->buffer == NULL) { 900 if (mp4->buffer == NULL) {
887 mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size); 901 mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size);
888 if (mp4->buffer == NULL) { 902 if (mp4->buffer == NULL) {
889 return NGX_ERROR; 903 return NGX_ERROR;
890 } 904 }
891 905
892 mp4->buffer_start = mp4->buffer; 906 mp4->buffer_start = mp4->buffer;
893 mp4->buffer_end = mp4->buffer + mp4->buffer_size;
894 } 907 }
895 908
896 n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size, 909 n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size,
897 mp4->offset); 910 mp4->offset);
898 911
899 if (n == NGX_ERROR) { 912 if (n == NGX_ERROR) {
900 return NGX_ERROR; 913 return NGX_ERROR;
901 } 914 }
902 915
903 if (n == 0) { 916 if ((size_t) n != mp4->buffer_size) {
904 return NGX_OK; 917 ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0,
918 ngx_read_file_n " read only %z of %z from \"%s\"",
919 n, mp4->buffer_size, mp4->file.name.data);
920 return NGX_ERROR;
905 } 921 }
906 922
907 mp4->buffer_pos = mp4->buffer_start; 923 mp4->buffer_pos = mp4->buffer_start;
924 mp4->buffer_end = mp4->buffer_start + mp4->buffer_size;
908 925
909 return NGX_OK; 926 return NGX_OK;
910 } 927 }
911 928
912 929
917 size_t atom_size; 934 size_t atom_size;
918 ngx_buf_t *atom; 935 ngx_buf_t *atom;
919 936
920 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); 937 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom");
921 938
922 if (atom_data_size > 1024) { 939 if (atom_data_size > 1024
940 || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end)
941 {
923 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 942 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
924 "\"%s\" mp4 ftyp atom is too large:%uL", 943 "\"%s\" mp4 ftyp atom is too large:%uL",
925 mp4->file.name.data, atom_data_size); 944 mp4->file.name.data, atom_data_size);
926 return NGX_ERROR; 945 return NGX_ERROR;
927 } 946 }
1166 atom_header = ngx_mp4_atom_header(mp4); 1185 atom_header = ngx_mp4_atom_header(mp4);
1167 mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header; 1186 mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header;
1168 mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header; 1187 mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header;
1169 ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd'); 1188 ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd');
1170 1189
1190 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) {
1191 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1192 "\"%s\" mp4 mvhd atom too small", mp4->file.name.data);
1193 return NGX_ERROR;
1194 }
1195
1171 if (mvhd_atom->version[0] == 0) { 1196 if (mvhd_atom->version[0] == 0) {
1172 /* version 0: 32-bit duration */ 1197 /* version 0: 32-bit duration */
1173 timescale = ngx_mp4_get_32value(mvhd_atom->timescale); 1198 timescale = ngx_mp4_get_32value(mvhd_atom->timescale);
1174 duration = ngx_mp4_get_32value(mvhd_atom->duration); 1199 duration = ngx_mp4_get_32value(mvhd_atom->duration);
1175 1200
1176 } else { 1201 } else {
1177 /* version 1: 64-bit duration */ 1202 /* version 1: 64-bit duration */
1203
1204 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) {
1205 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1206 "\"%s\" mp4 mvhd atom too small",
1207 mp4->file.name.data);
1208 return NGX_ERROR;
1209 }
1210
1178 timescale = ngx_mp4_get_32value(mvhd64_atom->timescale); 1211 timescale = ngx_mp4_get_32value(mvhd64_atom->timescale);
1179 duration = ngx_mp4_get_64value(mvhd64_atom->duration); 1212 duration = ngx_mp4_get_64value(mvhd64_atom->duration);
1180 } 1213 }
1181 1214
1182 mp4->timescale = timescale; 1215 mp4->timescale = timescale;
1343 atom_header = ngx_mp4_atom_header(mp4); 1376 atom_header = ngx_mp4_atom_header(mp4);
1344 tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header; 1377 tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header;
1345 tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header; 1378 tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header;
1346 ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd'); 1379 ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd');
1347 1380
1381 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) {
1382 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1383 "\"%s\" mp4 tkhd atom too small", mp4->file.name.data);
1384 return NGX_ERROR;
1385 }
1386
1348 if (tkhd_atom->version[0] == 0) { 1387 if (tkhd_atom->version[0] == 0) {
1349 /* version 0: 32-bit duration */ 1388 /* version 0: 32-bit duration */
1350 duration = ngx_mp4_get_32value(tkhd_atom->duration); 1389 duration = ngx_mp4_get_32value(tkhd_atom->duration);
1351 1390
1352 } else { 1391 } else {
1353 /* version 1: 64-bit duration */ 1392 /* version 1: 64-bit duration */
1393
1394 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) {
1395 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1396 "\"%s\" mp4 tkhd atom too small",
1397 mp4->file.name.data);
1398 return NGX_ERROR;
1399 }
1400
1354 duration = ngx_mp4_get_64value(tkhd64_atom->duration); 1401 duration = ngx_mp4_get_64value(tkhd64_atom->duration);
1355 } 1402 }
1356 1403
1357 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 1404 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1358 "tkhd duration:%uL, time:%.3fs", 1405 "tkhd duration:%uL, time:%.3fs",
1472 atom_header = ngx_mp4_atom_header(mp4); 1519 atom_header = ngx_mp4_atom_header(mp4);
1473 mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header; 1520 mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header;
1474 mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header; 1521 mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header;
1475 ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd'); 1522 ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd');
1476 1523
1524 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) {
1525 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1526 "\"%s\" mp4 mdhd atom too small", mp4->file.name.data);
1527 return NGX_ERROR;
1528 }
1529
1477 if (mdhd_atom->version[0] == 0) { 1530 if (mdhd_atom->version[0] == 0) {
1478 /* version 0: everything is 32-bit */ 1531 /* version 0: everything is 32-bit */
1479 timescale = ngx_mp4_get_32value(mdhd_atom->timescale); 1532 timescale = ngx_mp4_get_32value(mdhd_atom->timescale);
1480 duration = ngx_mp4_get_32value(mdhd_atom->duration); 1533 duration = ngx_mp4_get_32value(mdhd_atom->duration);
1481 1534
1482 } else { 1535 } else {
1483 /* version 1: 64-bit duration and 32-bit timescale */ 1536 /* version 1: 64-bit duration and 32-bit timescale */
1537
1538 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) {
1539 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1540 "\"%s\" mp4 mdhd atom too small",
1541 mp4->file.name.data);
1542 return NGX_ERROR;
1543 }
1544
1484 timescale = ngx_mp4_get_32value(mdhd64_atom->timescale); 1545 timescale = ngx_mp4_get_32value(mdhd64_atom->timescale);
1485 duration = ngx_mp4_get_64value(mdhd64_atom->duration); 1546 duration = ngx_mp4_get_64value(mdhd64_atom->duration);
1486 } 1547 }
1487 1548
1488 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 1549 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1754 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; 1815 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
1755 atom_table = atom_header + atom_size; 1816 atom_table = atom_header + atom_size;
1756 ngx_mp4_set_32value(stsd_atom->size, atom_size); 1817 ngx_mp4_set_32value(stsd_atom->size, atom_size);
1757 ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd'); 1818 ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd');
1758 1819
1759 if ((uint64_t) (sizeof(ngx_mp4_stsd_atom_t) - sizeof(ngx_mp4_atom_header_t)) 1820 if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) {
1760 > atom_data_size)
1761 {
1762 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 1821 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1763 "\"%s\" mp4 stsd atom too large", 1822 "\"%s\" mp4 stsd atom too small", mp4->file.name.data);
1764 mp4->file.name.data);
1765 return NGX_ERROR; 1823 return NGX_ERROR;
1766 } 1824 }
1767 1825
1768 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 1826 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1769 "stsd entries:%uD, media:%*s", 1827 "stsd entries:%uD, media:%*s",
1823 1881
1824 atom_header = ngx_mp4_atom_header(mp4); 1882 atom_header = ngx_mp4_atom_header(mp4);
1825 stts_atom = (ngx_mp4_stts_atom_t *) atom_header; 1883 stts_atom = (ngx_mp4_stts_atom_t *) atom_header;
1826 ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's'); 1884 ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's');
1827 1885
1886 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) {
1887 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1888 "\"%s\" mp4 stts atom too small", mp4->file.name.data);
1889 return NGX_ERROR;
1890 }
1891
1828 entries = ngx_mp4_get_32value(stts_atom->entries); 1892 entries = ngx_mp4_get_32value(stts_atom->entries);
1829 1893
1830 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 1894 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1831 "mp4 time-to-sample entries:%uD", entries); 1895 "mp4 time-to-sample entries:%uD", entries);
1832 1896
1897 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t)
1898 + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size)
1899 {
1900 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1901 "\"%s\" mp4 stts atom too small", mp4->file.name.data);
1902 return NGX_ERROR;
1903 }
1904
1833 atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t); 1905 atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t);
1834 atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t); 1906 atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t);
1835
1836 if ((uint64_t) (atom_end - stts_atom->version) > atom_data_size) {
1837 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1838 "\"%s\" mp4 stts atom too large",
1839 mp4->file.name.data);
1840 return NGX_ERROR;
1841 }
1842 1907
1843 trak = ngx_mp4_last_trak(mp4); 1908 trak = ngx_mp4_last_trak(mp4);
1844 trak->time_to_sample_entries = entries; 1909 trak->time_to_sample_entries = entries;
1845 1910
1846 atom = &trak->stts_atom_buf; 1911 atom = &trak->stts_atom_buf;
1908 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 1973 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1909 "count:%uD, duration:%uD", count, duration); 1974 "count:%uD, duration:%uD", count, duration);
1910 1975
1911 if (start_time < (uint64_t) count * duration) { 1976 if (start_time < (uint64_t) count * duration) {
1912 start_sample += (ngx_uint_t) (start_time / duration); 1977 start_sample += (ngx_uint_t) (start_time / duration);
1913 count -= start_sample; 1978 count -= (uint32_t) (start_time / duration);
1914 ngx_mp4_set_32value(entry->count, count); 1979 ngx_mp4_set_32value(entry->count, count);
1915 goto found; 1980 goto found;
1916 } 1981 }
1917 1982
1918 start_sample += count; 1983 start_sample += count;
1971 2036
1972 atom_header = ngx_mp4_atom_header(mp4); 2037 atom_header = ngx_mp4_atom_header(mp4);
1973 stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header; 2038 stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header;
1974 ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's'); 2039 ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's');
1975 2040
2041 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) {
2042 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2043 "\"%s\" mp4 stss atom too small", mp4->file.name.data);
2044 return NGX_ERROR;
2045 }
2046
1976 entries = ngx_mp4_get_32value(stss_atom->entries); 2047 entries = ngx_mp4_get_32value(stss_atom->entries);
1977 2048
1978 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 2049 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1979 "sync sample entries:%uD", entries); 2050 "sync sample entries:%uD", entries);
1980 2051
1986 atom = &trak->stss_atom_buf; 2057 atom = &trak->stss_atom_buf;
1987 atom->temporary = 1; 2058 atom->temporary = 1;
1988 atom->pos = atom_header; 2059 atom->pos = atom_header;
1989 atom->last = atom_table; 2060 atom->last = atom_table;
1990 2061
2062 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t)
2063 + entries * sizeof(uint32_t) > atom_data_size)
2064 {
2065 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2066 "\"%s\" mp4 stss atom too small", mp4->file.name.data);
2067 return NGX_ERROR;
2068 }
2069
1991 atom_end = atom_table + entries * sizeof(uint32_t); 2070 atom_end = atom_table + entries * sizeof(uint32_t);
1992
1993 if ((uint64_t) (atom_end - stss_atom->version) > atom_data_size) {
1994 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1995 "\"%s\" mp4 stss atom too large", mp4->file.name.data);
1996 return NGX_ERROR;
1997 }
1998 2071
1999 data = &trak->stss_data_buf; 2072 data = &trak->stss_data_buf;
2000 data->temporary = 1; 2073 data->temporary = 1;
2001 data->pos = atom_table; 2074 data->pos = atom_table;
2002 data->last = atom_end; 2075 data->last = atom_end;
2116 2189
2117 atom_header = ngx_mp4_atom_header(mp4); 2190 atom_header = ngx_mp4_atom_header(mp4);
2118 ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header; 2191 ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header;
2119 ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's'); 2192 ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's');
2120 2193
2194 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) {
2195 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2196 "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
2197 return NGX_ERROR;
2198 }
2199
2121 entries = ngx_mp4_get_32value(ctts_atom->entries); 2200 entries = ngx_mp4_get_32value(ctts_atom->entries);
2122 2201
2123 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 2202 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2124 "composition offset entries:%uD", entries); 2203 "composition offset entries:%uD", entries);
2125 2204
2131 atom = &trak->ctts_atom_buf; 2210 atom = &trak->ctts_atom_buf;
2132 atom->temporary = 1; 2211 atom->temporary = 1;
2133 atom->pos = atom_header; 2212 atom->pos = atom_header;
2134 atom->last = atom_table; 2213 atom->last = atom_table;
2135 2214
2215 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t)
2216 + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size)
2217 {
2218 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2219 "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
2220 return NGX_ERROR;
2221 }
2222
2136 atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t); 2223 atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t);
2137
2138 if ((uint64_t) (atom_end - ctts_atom->version) > atom_data_size) {
2139 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2140 "\"%s\" mp4 ctts atom too large", mp4->file.name.data);
2141 return NGX_ERROR;
2142 }
2143 2224
2144 data = &trak->ctts_data_buf; 2225 data = &trak->ctts_data_buf;
2145 data->temporary = 1; 2226 data->temporary = 1;
2146 data->pos = atom_table; 2227 data->pos = atom_table;
2147 data->last = atom_end; 2228 data->last = atom_end;
2249 2330
2250 atom_header = ngx_mp4_atom_header(mp4); 2331 atom_header = ngx_mp4_atom_header(mp4);
2251 stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header; 2332 stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header;
2252 ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c'); 2333 ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c');
2253 2334
2335 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) {
2336 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2337 "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
2338 return NGX_ERROR;
2339 }
2340
2254 entries = ngx_mp4_get_32value(stsc_atom->entries); 2341 entries = ngx_mp4_get_32value(stsc_atom->entries);
2255 2342
2256 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 2343 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2257 "sample-to-chunk entries:%uD", entries); 2344 "sample-to-chunk entries:%uD", entries);
2258 2345
2346 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t)
2347 + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size)
2348 {
2349 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2350 "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
2351 return NGX_ERROR;
2352 }
2353
2259 atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t); 2354 atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t);
2260 atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t); 2355 atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t);
2261
2262 if ((uint64_t) (atom_end - stsc_atom->version) > atom_data_size) {
2263 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2264 "\"%s\" mp4 stsc atom too large",
2265 mp4->file.name.data);
2266 return NGX_ERROR;
2267 }
2268 2356
2269 trak = ngx_mp4_last_trak(mp4); 2357 trak = ngx_mp4_last_trak(mp4);
2270 trak->sample_to_chunk_entries = entries; 2358 trak->sample_to_chunk_entries = entries;
2271 2359
2272 atom = &trak->stsc_atom_buf; 2360 atom = &trak->stsc_atom_buf;
2311 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf; 2399 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
2312 2400
2313 if (data == NULL) { 2401 if (data == NULL) {
2314 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 2402 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2315 "no mp4 stsc atoms were found in \"%s\"", 2403 "no mp4 stsc atoms were found in \"%s\"",
2404 mp4->file.name.data);
2405 return NGX_ERROR;
2406 }
2407
2408 if (trak->sample_to_chunk_entries == 0) {
2409 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2410 "zero number of entries in stsc atom in \"%s\"",
2316 mp4->file.name.data); 2411 mp4->file.name.data);
2317 return NGX_ERROR; 2412 return NGX_ERROR;
2318 } 2413 }
2319 2414
2320 start_sample = (uint32_t) trak->start_sample; 2415 start_sample = (uint32_t) trak->start_sample;
2456 2551
2457 atom_header = ngx_mp4_atom_header(mp4); 2552 atom_header = ngx_mp4_atom_header(mp4);
2458 stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header; 2553 stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header;
2459 ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z'); 2554 ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z');
2460 2555
2556 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) {
2557 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2558 "\"%s\" mp4 stsz atom too small", mp4->file.name.data);
2559 return NGX_ERROR;
2560 }
2561
2461 size = ngx_mp4_get_32value(stsz_atom->uniform_size); 2562 size = ngx_mp4_get_32value(stsz_atom->uniform_size);
2462 entries = ngx_mp4_get_32value(stsz_atom->entries); 2563 entries = ngx_mp4_get_32value(stsz_atom->entries);
2463 2564
2464 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, 2565 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2465 "sample uniform size:%uD, entries:%uD", size, entries); 2566 "sample uniform size:%uD, entries:%uD", size, entries);
2475 atom->last = atom_table; 2576 atom->last = atom_table;
2476 2577
2477 trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom; 2578 trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom;
2478 2579
2479 if (size == 0) { 2580 if (size == 0) {
2480 atom_end = atom_table + entries * sizeof(uint32_t); 2581 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t)
2481 2582 + entries * sizeof(uint32_t) > atom_data_size)
2482 if ((uint64_t) (atom_end - stsz_atom->version) > atom_data_size) { 2583 {
2483 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 2584 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2484 "\"%s\" mp4 stsz atom too large", 2585 "\"%s\" mp4 stsz atom too small",
2485 mp4->file.name.data); 2586 mp4->file.name.data);
2486 return NGX_ERROR; 2587 return NGX_ERROR;
2487 } 2588 }
2589
2590 atom_end = atom_table + entries * sizeof(uint32_t);
2488 2591
2489 data = &trak->stsz_data_buf; 2592 data = &trak->stsz_data_buf;
2490 data->temporary = 1; 2593 data->temporary = 1;
2491 data->pos = atom_table; 2594 data->pos = atom_table;
2492 data->last = atom_end; 2595 data->last = atom_end;
2505 2608
2506 return NGX_OK; 2609 return NGX_OK;
2507 } 2610 }
2508 2611
2509 2612
2510 static void 2613 static ngx_int_t
2511 ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, 2614 ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
2512 ngx_http_mp4_trak_t *trak) 2615 ngx_http_mp4_trak_t *trak)
2513 { 2616 {
2514 size_t atom_size; 2617 size_t atom_size;
2515 uint32_t *pos, *end; 2618 uint32_t *pos, *end;
2526 "mp4 stsz atom update"); 2629 "mp4 stsz atom update");
2527 2630
2528 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf; 2631 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
2529 2632
2530 if (data) { 2633 if (data) {
2634 if (trak->start_sample > trak->sample_sizes_entries) {
2635 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2636 "start time is out mp4 stsz samples in \"%s\"",
2637 mp4->file.name.data);
2638 return NGX_ERROR;
2639 }
2640
2531 data->pos += trak->start_sample * sizeof(uint32_t); 2641 data->pos += trak->start_sample * sizeof(uint32_t);
2532 end = (uint32_t *) data->pos; 2642 end = (uint32_t *) data->pos;
2533 2643
2534 for (pos = end - trak->chunk_samples; pos < end; pos++) { 2644 for (pos = end - trak->chunk_samples; pos < end; pos++) {
2535 trak->chunk_samples_size += ngx_mp4_get_32value(pos); 2645 trak->chunk_samples_size += ngx_mp4_get_32value(pos);
2546 2656
2547 ngx_mp4_set_32value(stsz_atom->size, atom_size); 2657 ngx_mp4_set_32value(stsz_atom->size, atom_size);
2548 ngx_mp4_set_32value(stsz_atom->entries, 2658 ngx_mp4_set_32value(stsz_atom->entries,
2549 trak->sample_sizes_entries - trak->start_sample); 2659 trak->sample_sizes_entries - trak->start_sample);
2550 } 2660 }
2661
2662 return NGX_OK;
2551 } 2663 }
2552 2664
2553 2665
2554 typedef struct { 2666 typedef struct {
2555 u_char size[4]; 2667 u_char size[4];
2575 2687
2576 atom_header = ngx_mp4_atom_header(mp4); 2688 atom_header = ngx_mp4_atom_header(mp4);
2577 stco_atom = (ngx_mp4_stco_atom_t *) atom_header; 2689 stco_atom = (ngx_mp4_stco_atom_t *) atom_header;
2578 ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o'); 2690 ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o');
2579 2691
2692 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) {
2693 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2694 "\"%s\" mp4 stco atom too small", mp4->file.name.data);
2695 return NGX_ERROR;
2696 }
2697
2580 entries = ngx_mp4_get_32value(stco_atom->entries); 2698 entries = ngx_mp4_get_32value(stco_atom->entries);
2581 2699
2582 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); 2700 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
2701
2702 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t)
2703 + entries * sizeof(uint32_t) > atom_data_size)
2704 {
2705 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2706 "\"%s\" mp4 stco atom too small", mp4->file.name.data);
2707 return NGX_ERROR;
2708 }
2583 2709
2584 atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t); 2710 atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t);
2585 atom_end = atom_table + entries * sizeof(uint32_t); 2711 atom_end = atom_table + entries * sizeof(uint32_t);
2586
2587 if ((uint64_t) (atom_end - stco_atom->version) > atom_data_size) {
2588 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2589 "\"%s\" mp4 stco atom too large", mp4->file.name.data);
2590 return NGX_ERROR;
2591 }
2592 2712
2593 trak = ngx_mp4_last_trak(mp4); 2713 trak = ngx_mp4_last_trak(mp4);
2594 trak->chunks = entries; 2714 trak->chunks = entries;
2595 2715
2596 atom = &trak->stco_atom_buf; 2716 atom = &trak->stco_atom_buf;
2632 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf; 2752 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf;
2633 2753
2634 if (data == NULL) { 2754 if (data == NULL) {
2635 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, 2755 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2636 "no mp4 stco atoms were found in \"%s\"", 2756 "no mp4 stco atoms were found in \"%s\"",
2757 mp4->file.name.data);
2758 return NGX_ERROR;
2759 }
2760
2761 if (trak->start_chunk > trak->chunks) {
2762 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2763 "start time is out mp4 stco chunks in \"%s\"",
2637 mp4->file.name.data); 2764 mp4->file.name.data);
2638 return NGX_ERROR; 2765 return NGX_ERROR;
2639 } 2766 }
2640 2767
2641 data->pos += trak->start_chunk * sizeof(uint32_t); 2768 data->pos += trak->start_chunk * sizeof(uint32_t);
2711 2838
2712 atom_header = ngx_mp4_atom_header(mp4); 2839 atom_header = ngx_mp4_atom_header(mp4);
2713 co64_atom = (ngx_mp4_co64_atom_t *) atom_header; 2840 co64_atom = (ngx_mp4_co64_atom_t *) atom_header;
2714 ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4'); 2841 ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4');
2715 2842
2843 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) {
2844 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2845 "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
2846 return NGX_ERROR;
2847 }
2848
2716 entries = ngx_mp4_get_32value(co64_atom->entries); 2849 entries = ngx_mp4_get_32value(co64_atom->entries);
2717 2850
2718 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); 2851 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
2852
2853 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t)
2854 + entries * sizeof(uint64_t) > atom_data_size)
2855 {
2856 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2857 "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
2858 return NGX_ERROR;
2859 }
2719 2860
2720 atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t); 2861 atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t);
2721 atom_end = atom_table + entries * sizeof(uint64_t); 2862 atom_end = atom_table + entries * sizeof(uint64_t);
2722
2723 if ((uint64_t) (atom_end - co64_atom->version) > atom_data_size) {
2724 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2725 "\"%s\" mp4 co64 atom too large", mp4->file.name.data);
2726 return NGX_ERROR;
2727 }
2728 2863
2729 trak = ngx_mp4_last_trak(mp4); 2864 trak = ngx_mp4_last_trak(mp4);
2730 trak->chunks = entries; 2865 trak->chunks = entries;
2731 2866
2732 atom = &trak->co64_atom_buf; 2867 atom = &trak->co64_atom_buf;
2772 "no mp4 co64 atoms were found in \"%s\"", 2907 "no mp4 co64 atoms were found in \"%s\"",
2773 mp4->file.name.data); 2908 mp4->file.name.data);
2774 return NGX_ERROR; 2909 return NGX_ERROR;
2775 } 2910 }
2776 2911
2912 if (trak->start_chunk > trak->chunks) {
2913 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2914 "start time is out mp4 co64 chunks in \"%s\"",
2915 mp4->file.name.data);
2916 return NGX_ERROR;
2917 }
2918
2777 data->pos += trak->start_chunk * sizeof(uint64_t); 2919 data->pos += trak->start_chunk * sizeof(uint64_t);
2778 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos); 2920 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
2779 trak->size += atom_size; 2921 trak->size += atom_size;
2780 2922
2781 trak->start_offset = ngx_mp4_get_64value(data->pos); 2923 trak->start_offset = ngx_mp4_get_64value(data->pos);