@@ -404,6 +404,9 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
404
404
msanread (key , t .key .size )
405
405
}
406
406
if h == nil || h .count == 0 {
407
+ if t .hashMightPanic () {
408
+ t .key .alg .hash (key , 0 ) // see issue 23734
409
+ }
407
410
return unsafe .Pointer (& zeroVal [0 ])
408
411
}
409
412
if h .flags & hashWriting != 0 {
@@ -434,12 +437,12 @@ bucketloop:
434
437
continue
435
438
}
436
439
k := add (unsafe .Pointer (b ), dataOffset + i * uintptr (t .keysize ))
437
- if t .indirectkey {
440
+ if t .indirectkey () {
438
441
k = * ((* unsafe .Pointer )(k ))
439
442
}
440
443
if alg .equal (key , k ) {
441
444
v := add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ i * uintptr (t .valuesize ))
442
- if t .indirectvalue {
445
+ if t .indirectvalue () {
443
446
v = * ((* unsafe .Pointer )(v ))
444
447
}
445
448
return v
@@ -460,6 +463,9 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
460
463
msanread (key , t .key .size )
461
464
}
462
465
if h == nil || h .count == 0 {
466
+ if t .hashMightPanic () {
467
+ t .key .alg .hash (key , 0 ) // see issue 23734
468
+ }
463
469
return unsafe .Pointer (& zeroVal [0 ]), false
464
470
}
465
471
if h .flags & hashWriting != 0 {
@@ -490,12 +496,12 @@ bucketloop:
490
496
continue
491
497
}
492
498
k := add (unsafe .Pointer (b ), dataOffset + i * uintptr (t .keysize ))
493
- if t .indirectkey {
499
+ if t .indirectkey () {
494
500
k = * ((* unsafe .Pointer )(k ))
495
501
}
496
502
if alg .equal (key , k ) {
497
503
v := add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ i * uintptr (t .valuesize ))
498
- if t .indirectvalue {
504
+ if t .indirectvalue () {
499
505
v = * ((* unsafe .Pointer )(v ))
500
506
}
501
507
return v , true
@@ -535,12 +541,12 @@ bucketloop:
535
541
continue
536
542
}
537
543
k := add (unsafe .Pointer (b ), dataOffset + i * uintptr (t .keysize ))
538
- if t .indirectkey {
544
+ if t .indirectkey () {
539
545
k = * ((* unsafe .Pointer )(k ))
540
546
}
541
547
if alg .equal (key , k ) {
542
548
v := add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ i * uintptr (t .valuesize ))
543
- if t .indirectvalue {
549
+ if t .indirectvalue () {
544
550
v = * ((* unsafe .Pointer )(v ))
545
551
}
546
552
return k , v
@@ -620,14 +626,14 @@ bucketloop:
620
626
continue
621
627
}
622
628
k := add (unsafe .Pointer (b ), dataOffset + i * uintptr (t .keysize ))
623
- if t .indirectkey {
629
+ if t .indirectkey () {
624
630
k = * ((* unsafe .Pointer )(k ))
625
631
}
626
632
if ! alg .equal (key , k ) {
627
633
continue
628
634
}
629
635
// already have a mapping for key. Update it.
630
- if t .needkeyupdate {
636
+ if t .needkeyupdate () {
631
637
typedmemmove (t .key , k , key )
632
638
}
633
639
val = add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ i * uintptr (t .valuesize ))
@@ -658,12 +664,12 @@ bucketloop:
658
664
}
659
665
660
666
// store new key/value at insert position
661
- if t .indirectkey {
667
+ if t .indirectkey () {
662
668
kmem := newobject (t .key )
663
669
* (* unsafe .Pointer )(insertk ) = kmem
664
670
insertk = kmem
665
671
}
666
- if t .indirectvalue {
672
+ if t .indirectvalue () {
667
673
vmem := newobject (t .elem )
668
674
* (* unsafe .Pointer )(val ) = vmem
669
675
}
@@ -676,7 +682,7 @@ done:
676
682
throw ("concurrent map writes" )
677
683
}
678
684
h .flags &^= hashWriting
679
- if t .indirectvalue {
685
+ if t .indirectvalue () {
680
686
val = * ((* unsafe .Pointer )(val ))
681
687
}
682
688
return val
@@ -693,6 +699,9 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
693
699
msanread (key , t .key .size )
694
700
}
695
701
if h == nil || h .count == 0 {
702
+ if t .hashMightPanic () {
703
+ t .key .alg .hash (key , 0 ) // see issue 23734
704
+ }
696
705
return
697
706
}
698
707
if h .flags & hashWriting != 0 {
@@ -724,20 +733,20 @@ search:
724
733
}
725
734
k := add (unsafe .Pointer (b ), dataOffset + i * uintptr (t .keysize ))
726
735
k2 := k
727
- if t .indirectkey {
736
+ if t .indirectkey () {
728
737
k2 = * ((* unsafe .Pointer )(k2 ))
729
738
}
730
739
if ! alg .equal (key , k2 ) {
731
740
continue
732
741
}
733
742
// Only clear key if there are pointers in it.
734
- if t .indirectkey {
743
+ if t .indirectkey () {
735
744
* (* unsafe .Pointer )(k ) = nil
736
745
} else if t .key .kind & kindNoPointers == 0 {
737
746
memclrHasPointers (k , t .key .size )
738
747
}
739
748
v := add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ i * uintptr (t .valuesize ))
740
- if t .indirectvalue {
749
+ if t .indirectvalue () {
741
750
* (* unsafe .Pointer )(v ) = nil
742
751
} else if t .elem .kind & kindNoPointers == 0 {
743
752
memclrHasPointers (v , t .elem .size )
@@ -897,7 +906,7 @@ next:
897
906
continue
898
907
}
899
908
k := add (unsafe .Pointer (b ), dataOffset + uintptr (offi )* uintptr (t .keysize ))
900
- if t .indirectkey {
909
+ if t .indirectkey () {
901
910
k = * ((* unsafe .Pointer )(k ))
902
911
}
903
912
v := add (unsafe .Pointer (b ), dataOffset + bucketCnt * uintptr (t .keysize )+ uintptr (offi )* uintptr (t .valuesize ))
@@ -909,7 +918,7 @@ next:
909
918
// through the oldbucket, skipping any keys that will go
910
919
// to the other new bucket (each oldbucket expands to two
911
920
// buckets during a grow).
912
- if t .reflexivekey || alg .equal (k , k ) {
921
+ if t .reflexivekey () || alg .equal (k , k ) {
913
922
// If the item in the oldbucket is not destined for
914
923
// the current new bucket in the iteration, skip it.
915
924
hash := alg .hash (k , uintptr (h .hash0 ))
@@ -930,13 +939,13 @@ next:
930
939
}
931
940
}
932
941
if (b .tophash [offi ] != evacuatedX && b .tophash [offi ] != evacuatedY ) ||
933
- ! (t .reflexivekey || alg .equal (k , k )) {
942
+ ! (t .reflexivekey () || alg .equal (k , k )) {
934
943
// This is the golden data, we can return it.
935
944
// OR
936
945
// key!=key, so the entry can't be deleted or updated, so we can just return it.
937
946
// That's lucky for us because when key!=key we can't look it up successfully.
938
947
it .key = k
939
- if t .indirectvalue {
948
+ if t .indirectvalue () {
940
949
v = * ((* unsafe .Pointer )(v ))
941
950
}
942
951
it .value = v
@@ -1160,15 +1169,15 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
1160
1169
throw ("bad map state" )
1161
1170
}
1162
1171
k2 := k
1163
- if t .indirectkey {
1172
+ if t .indirectkey () {
1164
1173
k2 = * ((* unsafe .Pointer )(k2 ))
1165
1174
}
1166
1175
var useY uint8
1167
1176
if ! h .sameSizeGrow () {
1168
1177
// Compute hash to make our evacuation decision (whether we need
1169
1178
// to send this key/value to bucket x or bucket y).
1170
1179
hash := t .key .alg .hash (k2 , uintptr (h .hash0 ))
1171
- if h .flags & iterator != 0 && ! t .reflexivekey && ! t .key .alg .equal (k2 , k2 ) {
1180
+ if h .flags & iterator != 0 && ! t .reflexivekey () && ! t .key .alg .equal (k2 , k2 ) {
1172
1181
// If key != key (NaNs), then the hash could be (and probably
1173
1182
// will be) entirely different from the old hash. Moreover,
1174
1183
// it isn't reproducible. Reproducibility is required in the
@@ -1203,12 +1212,12 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
1203
1212
dst .v = add (dst .k , bucketCnt * uintptr (t .keysize ))
1204
1213
}
1205
1214
dst .b .tophash [dst .i & (bucketCnt - 1 )] = top // mask dst.i as an optimization, to avoid a bounds check
1206
- if t .indirectkey {
1215
+ if t .indirectkey () {
1207
1216
* (* unsafe .Pointer )(dst .k ) = k2 // copy pointer
1208
1217
} else {
1209
1218
typedmemmove (t .key , dst .k , k ) // copy value
1210
1219
}
1211
- if t .indirectvalue {
1220
+ if t .indirectvalue () {
1212
1221
* (* unsafe .Pointer )(dst .v ) = * (* unsafe .Pointer )(v )
1213
1222
} else {
1214
1223
typedmemmove (t .elem , dst .v , v )
@@ -1274,12 +1283,12 @@ func reflect_makemap(t *maptype, cap int) *hmap {
1274
1283
if ! ismapkey (t .key ) {
1275
1284
throw ("runtime.reflect_makemap: unsupported map key type" )
1276
1285
}
1277
- if t .key .size > maxKeySize && (! t .indirectkey || t .keysize != uint8 (sys .PtrSize )) ||
1278
- t .key .size <= maxKeySize && (t .indirectkey || t .keysize != uint8 (t .key .size )) {
1286
+ if t .key .size > maxKeySize && (! t .indirectkey () || t .keysize != uint8 (sys .PtrSize )) ||
1287
+ t .key .size <= maxKeySize && (t .indirectkey () || t .keysize != uint8 (t .key .size )) {
1279
1288
throw ("key size wrong" )
1280
1289
}
1281
- if t .elem .size > maxValueSize && (! t .indirectvalue || t .valuesize != uint8 (sys .PtrSize )) ||
1282
- t .elem .size <= maxValueSize && (t .indirectvalue || t .valuesize != uint8 (t .elem .size )) {
1290
+ if t .elem .size > maxValueSize && (! t .indirectvalue () || t .valuesize != uint8 (sys .PtrSize )) ||
1291
+ t .elem .size <= maxValueSize && (t .indirectvalue () || t .valuesize != uint8 (t .elem .size )) {
1283
1292
throw ("value size wrong" )
1284
1293
}
1285
1294
if t .key .align > bucketCnt {
0 commit comments