@@ -426,6 +426,7 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state)
426
426
}
427
427
428
428
#define PARSE_ERROR_FRAGMENT_LEN 32
429
+
429
430
#ifdef RBIMPL_ATTR_NORETURN
430
431
RBIMPL_ATTR_NORETURN ()
431
432
#endif
@@ -830,21 +831,64 @@ static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig
830
831
return array ;
831
832
}
832
833
834
+ static VALUE json_find_duplicated_key (size_t count , const VALUE * pairs )
835
+ {
836
+ VALUE set = rb_hash_new_capa (count / 2 );
837
+ for (size_t index = 0 ; index < count ; index += 2 ) {
838
+ size_t before = RHASH_SIZE (set );
839
+ VALUE key = pairs [index ];
840
+ rb_hash_aset (set , key , Qtrue );
841
+ if (RHASH_SIZE (set ) == before ) {
842
+ if (RB_SYMBOL_P (key )) {
843
+ return rb_sym2str (key );
844
+ }
845
+ return key ;
846
+ }
847
+ }
848
+ return Qfalse ;
849
+ }
850
+
851
+ static void emit_duplicate_key_warning (JSON_ParserState * state , VALUE duplicate_key )
852
+ {
853
+ VALUE message = rb_sprintf (
854
+ "detected duplicate key %" PRIsVALUE " in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`" ,
855
+ rb_inspect (duplicate_key )
856
+ );
857
+
858
+ emit_parse_warning (RSTRING_PTR (message ), state );
859
+ RB_GC_GUARD (message );
860
+ }
861
+
862
+ #ifdef RBIMPL_ATTR_NORETURN
863
+ RBIMPL_ATTR_NORETURN ()
864
+ #endif
865
+ static void raise_duplicate_key_error (JSON_ParserState * state , VALUE duplicate_key )
866
+ {
867
+ VALUE message = rb_sprintf (
868
+ "duplicate key %" PRIsVALUE ,
869
+ rb_inspect (duplicate_key )
870
+ );
871
+
872
+ raise_parse_error (RSTRING_PTR (message ), state );
873
+ RB_GC_GUARD (message );
874
+ }
875
+
833
876
static inline VALUE json_decode_object (JSON_ParserState * state , JSON_ParserConfig * config , size_t count )
834
877
{
835
878
size_t entries_count = count / 2 ;
836
879
VALUE object = rb_hash_new_capa (entries_count );
837
- rb_hash_bulk_insert (count , rvalue_stack_peek (state -> stack , count ), object );
880
+ const VALUE * pairs = rvalue_stack_peek (state -> stack , count );
881
+ rb_hash_bulk_insert (count , pairs , object );
838
882
839
883
if (RB_UNLIKELY (RHASH_SIZE (object ) < entries_count )) {
840
884
switch (config -> on_duplicate_key ) {
841
885
case JSON_IGNORE :
842
886
break ;
843
887
case JSON_DEPRECATED :
844
- emit_parse_warning ( "detected duplicate keys in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`" , state );
888
+ emit_duplicate_key_warning ( state , json_find_duplicated_key ( count , pairs ) );
845
889
break ;
846
890
case JSON_RAISE :
847
- raise_parse_error ( "duplicate key" , state );
891
+ raise_duplicate_key_error ( state , json_find_duplicated_key ( count , pairs ) );
848
892
break ;
849
893
}
850
894
}
0 commit comments