]> git.kaiwu.me - njs.git/commitdiff
Parser: fix reference atom IDs on big-endian systems
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 22 Oct 2026 04:49:20 +0000 (21:49 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Fri, 23 Oct 2026 23:13:30 +0000 (16:13 -0700)
Previously, references to local variables and function arguments
failed with ReferenceError on 64-bit big-endian systems.  The parser
overwrote a uintptr_t reference atom ID through the overlapping
uint32_t value member, replacing the high half of the ID.

The issue was introduced in 9ff881e3 (1.0.2), which moved the
reference atom ID to the start of the parser node union.

Now, reference and value payloads share a uint32_t atom ID at the same
offset, initialized in the corresponding parser paths.
This removes the redundant value-member write and makes atom ID access
independent of byte order without increasing the parser node size.

This fixes #1143.

src/njs_generator.c
src/njs_parser.c
src/njs_parser.h
src/njs_variable.c
src/njs_variable.h

index a3215bcc8e791cf4e36bd8e16b400dda450de567..a45d5185344d9a82084481a7e8f17696cd063c55 100644 (file)
@@ -1348,7 +1348,7 @@ njs_generate_var_statement_after(njs_vm_t *vm, njs_generator_t *generator,
 
         if (name.length == 0) {
             njs_atom_to_value(vm, &expr->u.value.data.u.lambda->name,
-                              node->left->u.reference.atom_id);
+                              node->left->u.atom_id);
         }
     }
 
@@ -2514,7 +2514,7 @@ njs_generate_for_in_set_prop_block(njs_vm_t *vm, njs_generator_t *generator,
 
     if (prop->token_type == NJS_TOKEN_STRING
         || (prop->token_type == NJS_TOKEN_NUMBER
-            && prop->u.value.atom_id != NJS_ATOM_STRING_unknown))
+            && prop->u.atom_id != NJS_ATOM_STRING_unknown))
     {
         opcode = NJS_VMCODE_PROPERTY_ATOM_SET;
 
@@ -3248,7 +3248,7 @@ njs_generate_global_property_set(njs_vm_t *vm, njs_generator_t *generator,
         prop_set->value = node_dst->index;
         prop_set->object = njs_scope_global_this_index();
 
-        njs_atom_to_value(vm, &property,node_dst->u.reference.atom_id);
+        njs_atom_to_value(vm, &property, node_dst->u.atom_id);
 
         prop_set->property = njs_scope_global_index(vm, &property,
                                                 generator->runtime);
@@ -3411,7 +3411,7 @@ njs_generate_property_get_opcode(njs_parser_node_t *node)
 {
     if (node->token_type == NJS_TOKEN_STRING
         || (node->token_type == NJS_TOKEN_NUMBER
-            && node->u.value.atom_id != NJS_ATOM_STRING_unknown))
+            && node->u.atom_id != NJS_ATOM_STRING_unknown))
     {
         return NJS_VMCODE_PROPERTY_ATOM_GET;
     }
@@ -3425,7 +3425,7 @@ njs_generate_property_set_opcode(njs_parser_node_t *node)
 {
     if (node->token_type == NJS_TOKEN_STRING
         || (node->token_type == NJS_TOKEN_NUMBER
-            && node->u.value.atom_id != NJS_ATOM_STRING_unknown))
+            && node->u.atom_id != NJS_ATOM_STRING_unknown))
     {
         return NJS_VMCODE_PROPERTY_ATOM_SET;
     }
@@ -4598,7 +4598,7 @@ njs_generate_3addr_operation_end(njs_vm_t *vm, njs_generator_t *generator,
     if (node->u.operation == NJS_VMCODE_PROPERTY_GET
         && (right->token_type == NJS_TOKEN_STRING
             || (right->token_type == NJS_TOKEN_NUMBER
-                && right->u.value.atom_id != NJS_ATOM_STRING_unknown)))
+                && right->u.atom_id != NJS_ATOM_STRING_unknown)))
     {
         opcode = NJS_VMCODE_PROPERTY_ATOM_GET;
 
@@ -4842,7 +4842,7 @@ found:
 
     if (prop->token_type == NJS_TOKEN_STRING
         || (prop->token_type == NJS_TOKEN_NUMBER
-            && prop->u.value.atom_id != NJS_ATOM_STRING_unknown))
+            && prop->u.atom_id != NJS_ATOM_STRING_unknown))
     {
         opcode = NJS_VMCODE_PROPERTY_ATOM_GET;
 
@@ -4918,7 +4918,7 @@ njs_generate_function_declaration(njs_vm_t *vm, njs_generator_t *generator,
 
     lambda = njs_variable_lambda(var);
 
-    njs_atom_to_value(vm, &lambda->name, node->u.reference.atom_id);
+    njs_atom_to_value(vm, &lambda->name, node->u.atom_id);
     njs_string_get(vm, &lambda->name, &name);
 
     ret = njs_generate_function_scope(vm, generator, lambda, node, &name);
@@ -6457,7 +6457,7 @@ njs_generate_global_reference(njs_vm_t *vm, njs_generator_t *generator,
         return NJS_ERROR;
     }
 
-    njs_atom_to_value(vm, &property, node->u.reference.atom_id);
+    njs_atom_to_value(vm, &property, node->u.atom_id);
 
     prop_get->property = njs_scope_global_index(vm, &property,
                                                 generator->runtime);
@@ -6495,7 +6495,7 @@ njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator,
 
     ref_err->type = NJS_OBJ_TYPE_REF_ERROR;
 
-    njs_atom_string_get(vm, node->u.reference.atom_id, &entry);
+    njs_atom_string_get(vm, node->u.atom_id, &entry);
 
     return njs_name_copy(vm, &ref_err->u.name, &entry);
 }
index 79a07e31612777495cc43463a890b43e97280c35..0fd63bbba355cb636de1d398fa1c710bea3d6b03 100644 (file)
@@ -1064,7 +1064,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser,
         if (njs_number_is_integer_index(token->number)
             && token->number < 0x80000000)
         {
-            node->u.value.atom_id = njs_number_atom((uint32_t) token->number);
+            node->u.atom_id = njs_number_atom((uint32_t) token->number);
         }
 
         node->token_line = token->line;
@@ -1267,8 +1267,6 @@ reference:
         return NJS_ERROR;
     }
 
-    node->u.value.atom_id = token->atom_id;
-
     node->token_line = token->line;
     parser->node = node;
 
@@ -8214,6 +8212,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token)
 
     case NJS_TOKEN_NULL:
         njs_thread_log_debug("JS: null");
+        node->u.atom_id = token->atom_id;
         break;
 
     case NJS_TOKEN_THIS:
@@ -9001,15 +9000,12 @@ invalid:
 
 njs_int_t
 njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope,
-    njs_parser_node_t *node, uintptr_t atom_id)
+    njs_parser_node_t *node, uint32_t atom_id)
 {
     njs_rbtree_node_t         *rb_node;
-    njs_variable_reference_t  *vr;
     njs_parser_rbtree_node_t  parse_node, *rb_parse_node;
 
-    vr = &node->u.reference;
-
-    vr->atom_id = atom_id;
+    node->u.atom_id = atom_id;
 
     parse_node.key = atom_id;
 
index 16ceb3a8f612ab314b744e6a79a94a101170a1d6..604f34e5175042f2b29286aa848c6fa47e71ac91 100644 (file)
@@ -56,6 +56,8 @@ struct njs_parser_node_s {
             njs_arr_t               *items;
             uint32_t                length;
         } array;
+        /* Only reference and value payloads share this field. */
+        uint32_t                    atom_id;
         njs_variable_reference_t    reference;
         njs_value_t                 value;
         uintptr_t                   label;
@@ -156,7 +158,7 @@ njs_bool_t njs_variable_closure_test(njs_parser_scope_t *root,
 njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node);
 njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node);
 njs_int_t njs_parser_variable_reference(njs_parser_t *parser,
-    njs_parser_scope_t *scope, njs_parser_node_t *node, uintptr_t atom_id);
+    njs_parser_scope_t *scope, njs_parser_node_t *node, uint32_t atom_id);
 njs_token_type_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser,
     njs_str_t *name, njs_token_type_t type);
 njs_int_t njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token,
index 4f5ba0eae8225a165cc6411680c86fae99bda75e..6e21afd7516280d416eb66d090799108a5924a55 100644 (file)
@@ -369,15 +369,13 @@ njs_variable_closure_test(njs_parser_scope_t *root, njs_parser_scope_t *scope)
 njs_variable_t *
 njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node)
 {
-    njs_rbtree_node_t         *rb_node;
-    njs_parser_scope_t        *scope;
-    njs_variable_node_t       var_node;
-    njs_variable_reference_t  *ref;
+    njs_rbtree_node_t    *rb_node;
+    njs_parser_scope_t   *scope;
+    njs_variable_node_t  var_node;
 
-    ref = &node->u.reference;
     scope = node->scope;
 
-    var_node.key = ref->atom_id;
+    var_node.key = node->u.atom_id;
 
     do {
         rb_node = njs_rbtree_find(&scope->variables, &var_node.node);
@@ -510,7 +508,7 @@ njs_variable_reference(njs_vm_t *vm, njs_mp_t *mem_pool,
 
     closure = njs_variable_closure_test(node->scope, ref->variable->scope);
 
-    ref_node.key = ref->atom_id;
+    ref_node.key = node->u.atom_id;
 
     rb_node = njs_rbtree_find(&scope->references, &ref_node.node);
     if (njs_slow_path(rb_node == NULL)) {
index 8b89a427827f700564eb55bf62089a861598b6dc..a1b7707e39d82d6368c4070615fdfe4c9f6e0041 100644 (file)
@@ -44,7 +44,7 @@ typedef enum {
 
 
 typedef struct {
-    uintptr_t             atom_id;
+    uint32_t              atom_id;
     njs_variable_t        *variable;
 } njs_variable_reference_t;