static void ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx,
ngx_js_loc_conf_t *conf);
static ngx_int_t ngx_js_init_preload_vm(njs_vm_t *vm, ngx_js_loc_conf_t *conf);
+static ngx_int_t ngx_js_integer_in_range(double num);
static ngx_int_t ngx_njs_execute_pending_jobs(njs_vm_t *vm, ngx_log_t *log);
static njs_int_t ngx_njs_await(njs_vm_t *vm, ngx_log_t *log,
return NGX_ERROR;
}
+ if (!ngx_js_integer_in_range(num)) {
+ (void) JS_ThrowRangeError(cx, "number is out of range");
+ return NGX_ERROR;
+ }
+
*n = num;
return NGX_OK;
}
+static ngx_int_t
+ngx_js_integer_in_range(double num)
+{
+ ngx_int_t valid;
+
+#define NGX_JS_INT_T_LIMIT ((double) NGX_MAX_INT_T_VALUE + 1.0)
+
+ /*
+ * The ngx_int_t range is half-open in double: -limit is valid, while
+ * +limit is not. On 64-bit, NGX_MAX_INT_T_VALUE rounds to 2^63 as a
+ * double, so the expression still gives the exclusive upper bound.
+ */
+
+ valid = (num >= -NGX_JS_INT_T_LIMIT && num < NGX_JS_INT_T_LIMIT);
+
+#undef NGX_JS_INT_T_LIMIT
+
+ return valid;
+}
+
+
ngx_int_t
ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n)
{
+ double num;
+
if (!njs_value_is_valid_number(value)) {
njs_vm_error(vm, "is not a number");
return NGX_ERROR;
}
- *n = njs_value_number(value);
+ num = njs_value_number(value);
+
+ if (!ngx_js_integer_in_range(num)) {
+ njs_vm_range_error(vm, "number is out of range");
+ return NGX_ERROR;
+ }
+
+ *n = num;
return NGX_OK;
}
location /njs {
js_content test.njs;
}
+
+ location /status {
+ js_content test.status;
+ }
}
}
r.return(Number(r.args.c), body);
}
- export default {njs:test_njs, returnf};
+ function status(r) {
+ try {
+ r.status = Number(r.args.c);
+ r.return(200, r.status);
+
+ } catch (e) {
+ r.return(200, e.name + ': ' + e.message);
+ }
+ }
+
+ export default {njs:test_njs, returnf, status};
EOF
-$t->try_run('no njs return')->plan(7);
+$t->try_run('no njs return')->plan(8);
###############################################################################
like(http_get('/?c=301&t=path'), qr/ 301 .*Location: path/s, 'return redirect');
like(http_get('/?c=404'), qr/404 Not.*html/s, 'return error page');
like(http_get('/?c=inv'), qr/ 500 /, 'return invalid');
+like(http_get('/status?c=1e100'), qr/RangeError: number is out of range/,
+ 'status range');
TODO: {
local $TODO = 'not yet' unless has_version('0.8.6');