Skip to content

Commit

Permalink
Mp4: introduced custom version of ngx_atofp().
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mdounin committed Oct 27, 2016
1 parent 9ea918a commit 271d306
Showing 1 changed file with 60 additions and 14 deletions.
74 changes: 60 additions & 14 deletions src/http/modules/ngx_http_mp4_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ typedef struct {


static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_mp4_atofp(u_char *line, size_t n, size_t point);

static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
Expand Down Expand Up @@ -537,26 +538,15 @@ ngx_http_mp4_handler(ngx_http_request_t *r)

/*
* A Flash player may send start value with a lot of digits
* after dot so strtod() is used instead of atofp(). NaNs and
* infinities become negative numbers after (int) conversion.
* after dot so a custom function is used instead of ngx_atofp().
*/

ngx_set_errno(0);
start = (int) (strtod((char *) value.data, NULL) * 1000);

if (ngx_errno != 0) {
start = -1;
}
start = ngx_http_mp4_atofp(value.data, value.len, 3);
}

if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {

ngx_set_errno(0);
end = (int) (strtod((char *) value.data, NULL) * 1000);

if (ngx_errno != 0) {
end = -1;
}
end = ngx_http_mp4_atofp(value.data, value.len, 3);

if (end > 0) {
if (start < 0) {
Expand Down Expand Up @@ -686,6 +676,62 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
}


static ngx_int_t
ngx_http_mp4_atofp(u_char *line, size_t n, size_t point)
{
ngx_int_t value, cutoff, cutlim;
ngx_uint_t dot;

/* same as ngx_atofp(), but allows additional digits */

if (n == 0) {
return NGX_ERROR;
}

cutoff = NGX_MAX_INT_T_VALUE / 10;
cutlim = NGX_MAX_INT_T_VALUE % 10;

dot = 0;

for (value = 0; n--; line++) {

if (*line == '.') {
if (dot) {
return NGX_ERROR;
}

dot = 1;
continue;
}

if (*line < '0' || *line > '9') {
return NGX_ERROR;
}

if (point == 0) {
continue;
}

if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {
return NGX_ERROR;
}

value = value * 10 + (*line - '0');
point -= dot;
}

while (point--) {
if (value > cutoff) {
return NGX_ERROR;
}

value = value * 10;
}

return value;
}


static ngx_int_t
ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
{
Expand Down

0 comments on commit 271d306

Please sign in to comment.