Skip to content

Add bound checking to accelerated intrinsics#23937

Open
IBMJimmyk wants to merge 1 commit into
eclipse-openj9:masterfrom
IBMJimmyk:indexOfChk
Open

Add bound checking to accelerated intrinsics#23937
IBMJimmyk wants to merge 1 commit into
eclipse-openj9:masterfrom
IBMJimmyk:indexOfChk

Conversation

@IBMJimmyk

@IBMJimmyk IBMJimmyk commented May 19, 2026

Copy link
Copy Markdown
Contributor

Prior to JDK25, due to a race condition in AbstractStringBuilder, it is possible for some accelerated String intrinsics to perform an out of bounds array access. This applies to:

java/lang/StringLatin1.inflate([BI[CII)V
java/lang/StringLatin1.indexOf([BI[BII)I
java/lang/StringUTF16.indexOf([BI[BII)I

To address this, bound checking has been added such that the safe slow path code is performed in the rares cases that an out of bounds array access may occur.

Former behavior is restored via the TR_DisableStringIntrinsicFlagChk envvar. As the problem does not exist in JDK25, the bound checking is not added in JDK25 and onward.

Depends on:
eclipse-omr/omr#8255

Issue with more details here:
#23880
Original Issue the problem was found is here:
#23353

@IBMJimmyk IBMJimmyk force-pushed the indexOfChk branch 3 times, most recently from 19bbb96 to b2e97b6 Compare May 21, 2026 15:40
@IBMJimmyk

Copy link
Copy Markdown
Contributor Author

java/lang/StringLatin1.inflate([BI[CII)V example:
Before recognizedCallTransformer:

n2n       BBStart <block_2> (freq 10000)                                                      [0x7087d1404760] bci=[-1,0,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n11n      treetop                                                                             [0x7087d1404a30] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n10n        call  java/lang/StringLatin1.inflate([BI[CII)V[#429  final static Method] [flags 0x20500 0x0 ] ()  [0x7087d14049e0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=5 flg=0x20
n4n           aloadi  StringLatin1Test.inputByteArray [B[#422  Shadow +16] [flags 0x80607 0x0 ]  [0x7087d1404800] bci=[-1,1,119] rc=1 vc=0 vn=- li=- udi=- nc=1
n3n             aload  <'this' parm LStringLatin1Test;>[#418  Parm] [flags 0x40000107 0x0 ] (X!=0 )  [0x7087d14047b0] bci=[-1,0,119] rc=1 vc=0 vn=- li=- udi=- nc=0 flg=0x4
n5n           iload  <parm 1 I>[#419  Parm] [flags 0x40000103 0x0 ]                           [0x7087d1404850] bci=[-1,4,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n7n           aloadi  StringLatin1Test.outputCharArray [C[#423  Shadow +24] [flags 0x80607 0x0 ]  [0x7087d14048f0] bci=[-1,6,119] rc=1 vc=0 vn=- li=- udi=- nc=1
n6n             aload  <'this' parm LStringLatin1Test;>[#418  Parm] [flags 0x40000107 0x0 ] (X!=0 )  [0x7087d14048a0] bci=[-1,5,119] rc=1 vc=0 vn=- li=- udi=- nc=0 flg=0x4
n8n           iload  <parm 2 I>[#420  Parm] [flags 0x40000103 0x0 ]                           [0x7087d1404940] bci=[-1,9,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n9n           iload  <parm 3 I>[#421  Parm] [flags 0x40000103 0x0 ]                           [0x7087d1404990] bci=[-1,10,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n12n      return                                                                              [0x7087d1404a80] bci=[-1,14,120] rc=0 vc=0 vn=- li=- udi=- nc=0
n1n       BBEnd </block_2>                                                                    [0x7087d1404710] bci=[-1,14,120] rc=0 vc=0 vn=- li=- udi=- nc=0

After recognizedCallTransformer:

n2n       BBStart <block_2> (freq 10000)                                                      [0x7087d1404760] bci=[-1,0,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n13n      astore  <temp slot 5>[#430  Auto] [flags 0x7 0x0 ]                                  [0x7087d1404ad0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n4n         aloadi  StringLatin1Test.inputByteArray [B[#422  Shadow +16] [flags 0x80607 0x0 ]  [0x7087d1404800] bci=[-1,1,119] rc=1 vc=0 vn=- li=- udi=- nc=1
n3n           aload  <'this' parm LStringLatin1Test;>[#418  Parm] [flags 0x40000107 0x0 ] (X!=0 )  [0x7087d14047b0] bci=[-1,0,119] rc=1 vc=0 vn=- li=- udi=- nc=0 flg=0x4
n15n      istore  <temp slot 6>[#431  Auto] [flags 0x3 0x0 ]                                  [0x7087d1404b70] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n5n         iload  <parm 1 I>[#419  Parm] [flags 0x40000103 0x0 ]                             [0x7087d1404850] bci=[-1,4,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n17n      astore  <temp slot 7>[#432  Auto] [flags 0x7 0x0 ]                                  [0x7087d1404c10] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n7n         aloadi  StringLatin1Test.outputCharArray [C[#423  Shadow +24] [flags 0x80607 0x0 ]  [0x7087d14048f0] bci=[-1,6,119] rc=1 vc=0 vn=- li=- udi=- nc=1
n6n           aload  <'this' parm LStringLatin1Test;>[#418  Parm] [flags 0x40000107 0x0 ] (X!=0 )  [0x7087d14048a0] bci=[-1,5,119] rc=1 vc=0 vn=- li=- udi=- nc=0 flg=0x4
n19n      istore  <temp slot 8>[#433  Auto] [flags 0x3 0x0 ]                                  [0x7087d1404cb0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n8n         iload  <parm 2 I>[#420  Parm] [flags 0x40000103 0x0 ]                             [0x7087d1404940] bci=[-1,9,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n21n      istore  <temp slot 9>[#434  Auto] [flags 0x3 0x0 ]                                  [0x7087d1404d50] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n9n         iload  <parm 3 I>[#421  Parm] [flags 0x40000103 0x0 ]                             [0x7087d1404990] bci=[-1,10,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n47n      ificmplt --> block_4 BBStart at n52n ()                                             [0x7087d1405570] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=2 flg=0x20
n24n        arraylength (X>=0 )                                                               [0x7087d1404e40] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=1 flg=0x100
n23n          aload  <temp slot 5>[#430  Auto] [flags 0x7 0x0 ]                               [0x7087d1404df0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n43n        iadd                                                                              [0x7087d1405430] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=2
n42n          iload  <temp slot 6>[#431  Auto] [flags 0x3 0x0 ]                               [0x7087d14053e0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n41n          iload  <temp slot 9>[#434  Auto] [flags 0x3 0x0 ]                               [0x7087d1405390] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n50n      BBEnd </block_2> =====                                                              [0x7087d1405660] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0

n57n      BBStart <block_6> (freq 10000)                                                      [0x7087d14a0190] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n48n      ificmplt --> block_4 BBStart at n52n ()                                             [0x7087d14055c0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=2 flg=0x20
n26n        arraylength (X>=0 )                                                               [0x7087d1404ee0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=1 flg=0x100
n25n          aload  <temp slot 7>[#432  Auto] [flags 0x7 0x0 ]                               [0x7087d1404e90] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n46n        iadd                                                                              [0x7087d1405520] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=2
n45n          iload  <temp slot 8>[#433  Auto] [flags 0x3 0x0 ]                               [0x7087d14054d0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n44n          iload  <temp slot 9>[#434  Auto] [flags 0x3 0x0 ]                               [0x7087d1405480] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n56n      BBEnd </block_6> =====                                                              [0x7087d14a0140] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0

n55n      BBStart <block_5> (freq 10000)                                                      [0x7087d14a00f0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n34n      treetop                                                                             [0x7087d1405160] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n35n        call  java/lang/StringLatin1.inflate([BI[CII)V[#429  final static Method] [flags 0x20500 0x0 ] ()  [0x7087d14051b0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=5 flg=0x100020
n36n          aload  <temp slot 5>[#430  Auto] [flags 0x7 0x0 ]                               [0x7087d1405200] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n37n          iload  <temp slot 6>[#431  Auto] [flags 0x3 0x0 ]                               [0x7087d1405250] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n38n          aload  <temp slot 7>[#432  Auto] [flags 0x7 0x0 ]                               [0x7087d14052a0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n39n          iload  <temp slot 8>[#433  Auto] [flags 0x3 0x0 ]                               [0x7087d14052f0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n40n          iload  <temp slot 9>[#434  Auto] [flags 0x3 0x0 ]                               [0x7087d1405340] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n54n      BBEnd </block_5> =====                                                              [0x7087d14a00a0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0

n49n      BBStart <block_3> (freq 10000)                                                      [0x7087d1405610] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n12n      return                                                                              [0x7087d1404a80] bci=[-1,14,120] rc=0 vc=0 vn=- li=- udi=- nc=0
n1n       BBEnd </block_3> =====                                                              [0x7087d1404710] bci=[-1,14,120] rc=0 vc=0 vn=- li=- udi=- nc=0

n52n      BBStart <block_4> (freq 0) (cold)                                                   [0x7087d14a0000] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n27n      treetop                                                                             [0x7087d1404f30] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=1
n28n        call  java/lang/StringLatin1.inflate([BI[CII)V[#429  final static Method] [flags 0x20500 0x0 ] ()  [0x7087d1404f80] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=5 flg=0x200020
n29n          aload  <temp slot 5>[#430  Auto] [flags 0x7 0x0 ]                               [0x7087d1404fd0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n30n          iload  <temp slot 6>[#431  Auto] [flags 0x3 0x0 ]                               [0x7087d1405020] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n31n          aload  <temp slot 7>[#432  Auto] [flags 0x7 0x0 ]                               [0x7087d1405070] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n32n          iload  <temp slot 8>[#433  Auto] [flags 0x3 0x0 ]                               [0x7087d14050c0] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n33n          iload  <temp slot 9>[#434  Auto] [flags 0x3 0x0 ]                               [0x7087d1405110] bci=[-1,11,119] rc=1 vc=0 vn=- li=- udi=- nc=0
n53n      goto --> block_3 BBStart at n49n                                                    [0x7087d14a0050] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0
n51n      BBEnd </block_4> (cold)                                                             [0x7087d14056b0] bci=[-1,11,119] rc=0 vc=0 vn=- li=- udi=- nc=0

Block 2 is split into Block 2 and 3. A check is added at the end of block 2 to make sure the input array is big enough for the inflate operation. If so, the check in block 6 checks the length of the output array. If that is also good, the fast path version of inflate is called in block 5.

If either check fails, it jumps to block 4. Block 4 is the slow path and stays as a call out until the very end. This path should only be taken if the AbstractStringBuilder race condition is hit and messes up the array sizes.

@IBMJimmyk

Copy link
Copy Markdown
Contributor Author

java/lang/StringLatin1.indexOf([BI[BII)I example.
Before recognizedCallTransformer:

n147n     BBStart <block_8>                                                                   [0x71cdb44b1db0] bci=[0,57,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n160n     treetop                                                                             [0x71cdb44b21c0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n159n       icall  java/lang/StringLatin1.indexOf([BI[BII)I[#463  final static Method] [flags 0x20500 0x0 ] ()  [0x71cdb44b2170] bci=[0,65,3461] rc=2 vc=0 vn=- li=- udi=- nc=5 flg=0x20
n154n         aload  src<parm 0 [B>[#425  Parm] [flags 0x40000107 0x0 ]                       [0x71cdb44b1fe0] bci=[0,57,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n155n         iload  srcCount<parm 2 I>[#427  Parm] [flags 0x40000103 0x0 ]                   [0x71cdb44b2030] bci=[0,58,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n156n         aload  tgt<auto slot 6>[#454  Auto] [flags 0x7 0x0 ]                            [0x71cdb44b2080] bci=[0,59,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n157n         iload  tgtCount<auto slot 5>[#452  Auto] [flags 0x3 0x0 ]                       [0x71cdb44b20d0] bci=[0,61,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n158n         iload  fromIndex<parm 4 I>[#429  Parm] [flags 0x40000103 0x0 ]                  [0x71cdb44b2120] bci=[0,63,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n161n     istore  <pending push temp 0>[#464  Auto] [flags 0x3 0x800 ]                        [0x71cdb44b2210] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n159n       ==>icall
n163n     goto --> block_10 BBStart at n99n                                                   [0x71cdb44b22b0] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n146n     BBEnd </block_8> =====                                                              [0x71cdb44b1d60] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=0

After recognizedCallTransformer:

n147n     BBStart <block_8>                                                                   [0x71cdb44b1db0] bci=[0,57,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n183n     astore  <temp slot 9>[#477  Auto] [flags 0x7 0x0 ]                                  [0x71cdb44b28f0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n154n       aload  src<parm 0 [B>[#425  Parm] [flags 0x40000107 0x0 ]                         [0x71cdb44b1fe0] bci=[0,57,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n185n     istore  <temp slot 10>[#478  Auto] [flags 0x3 0x0 ]                                 [0x71cdb44b2990] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n155n       iload  srcCount<parm 2 I>[#427  Parm] [flags 0x40000103 0x0 ]                     [0x71cdb44b2030] bci=[0,58,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n187n     astore  <temp slot 11>[#479  Auto] [flags 0x7 0x0 ]                                 [0x71cdb44b2a30] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n156n       aload  tgt<auto slot 6>[#454  Auto] [flags 0x7 0x0 ]                              [0x71cdb44b2080] bci=[0,59,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n189n     istore  <temp slot 12>[#480  Auto] [flags 0x3 0x0 ]                                 [0x71cdb44b2ad0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n157n       iload  tgtCount<auto slot 5>[#452  Auto] [flags 0x3 0x0 ]                         [0x71cdb44b20d0] bci=[0,61,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n191n     istore  <temp slot 13>[#481  Auto] [flags 0x3 0x0 ]                                 [0x71cdb44b2b70] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n158n       iload  fromIndex<parm 4 I>[#429  Parm] [flags 0x40000103 0x0 ]                    [0x71cdb44b2120] bci=[0,63,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n211n     ificmpgt --> block_15 BBStart at n215n ()                                           [0x71cdb44b31b0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=2 flg=0x20
n210n       iload  <temp slot 10>[#478  Auto] [flags 0x3 0x0 ]                                [0x71cdb44b3160] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n194n       arraylength (X>=0 )                                                               [0x71cdb44b2c60] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=1 flg=0x100
n193n         aload  <temp slot 9>[#477  Auto] [flags 0x7 0x0 ]                               [0x71cdb44b2c10] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n213n     BBEnd </block_8> =====                                                              [0x71cdb44b3250] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0

n218n     BBStart <block_16>                                                                  [0x71cdb44b33e0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n202n     treetop                                                                             [0x71cdb44b2ee0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n203n       icall  java/lang/StringLatin1.indexOf([BI[BII)I[#463  final static Method] [flags 0x20500 0x0 ] ()  [0x71cdb44b2f30] bci=[0,65,3461] rc=2 vc=0 vn=- li=- udi=- nc=5 flg=0x100020
n204n         aload  <temp slot 9>[#477  Auto] [flags 0x7 0x0 ]                               [0x71cdb44b2f80] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n205n         iload  <temp slot 10>[#478  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b2fd0] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n206n         aload  <temp slot 11>[#479  Auto] [flags 0x7 0x0 ]                              [0x71cdb44b3020] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n207n         iload  <temp slot 12>[#480  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b3070] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n208n         iload  <temp slot 13>[#481  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b30c0] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n219n     istore  <temp slot 14>[#482  Auto] [flags 0x3 0x0 ]                                 [0x71cdb44b3430] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n203n       ==>icall
n217n     BBEnd </block_16> =====                                                             [0x71cdb44b3390] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0

n212n     BBStart <block_14>                                                                  [0x71cdb44b3200] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n161n     istore  <pending push temp 0>[#464  Auto] [flags 0x3 0x800 ]                        [0x71cdb44b2210] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n159n       iload  <temp slot 14>[#482  Auto] [flags 0x3 0x0 ] ()                             [0x71cdb44b2170] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0 flg=0x20
n163n     goto --> block_10 BBStart at n99n                                                   [0x71cdb44b22b0] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n146n     BBEnd </block_14> =====                                                             [0x71cdb44b1d60] bci=[0,68,3461] rc=0 vc=0 vn=- li=- udi=- nc=0

n215n     BBStart <block_15> (freq 0) (cold)                                                  [0x71cdb44b32f0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n195n     treetop                                                                             [0x71cdb44b2cb0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n196n       icall  java/lang/StringLatin1.indexOf([BI[BII)I[#463  final static Method] [flags 0x20500 0x0 ] ()  [0x71cdb44b2d00] bci=[0,65,3461] rc=2 vc=0 vn=- li=- udi=- nc=5 flg=0x200020
n197n         aload  <temp slot 9>[#477  Auto] [flags 0x7 0x0 ]                               [0x71cdb44b2d50] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n198n         iload  <temp slot 10>[#478  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b2da0] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n199n         aload  <temp slot 11>[#479  Auto] [flags 0x7 0x0 ]                              [0x71cdb44b2df0] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n200n         iload  <temp slot 12>[#480  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b2e40] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n201n         iload  <temp slot 13>[#481  Auto] [flags 0x3 0x0 ]                              [0x71cdb44b2e90] bci=[0,65,3461] rc=1 vc=0 vn=- li=- udi=- nc=0
n220n     istore  <temp slot 14>[#482  Auto] [flags 0x3 0x0 ]                                 [0x71cdb44b3480] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=1
n196n       ==>icall
n216n     goto --> block_14 BBStart at n212n                                                  [0x71cdb44b3340] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0
n214n     BBEnd </block_15> (cold) =====                                                      [0x71cdb44b32a0] bci=[0,65,3461] rc=0 vc=0 vn=- li=- udi=- nc=0

This is somewhat similar to how StringLatin1.inflate is handled. Even if the race condition is triggered, the target array is guaranteed to be good. So a check is only needed to confirm that the src array is big enough to hold the number of characters it is thought to have. If it isn't, it falls back to the slow path which calls out.

java/lang/StringUTF16.indexOf([BI[BII)I is also handled the same way except each character requires 2 bytes in the array to be recorded.

@IBMJimmyk IBMJimmyk changed the title WIP: Add bound checking to accelerated intrinsics Add bound checking to accelerated intrinsics May 26, 2026
@IBMJimmyk

Copy link
Copy Markdown
Contributor Author

The bulk of this change are common changes. But, there are some small codegen changes affecting Power, X, Z and Arm. So I need to tag a bunch of people here.

@hzongaro Can you take a look at the Common/X changes?
@zl-wang Can you take a look at the Power changes?
@0xdaryl Can you take a look at the Arm changes?
@r30shah Can you take a look at the Z changes?

@hzongaro hzongaro added comp:jit depends:omr Pull request is dependent on a corresponding change in OMR labels May 27, 2026

@zl-wang zl-wang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level comment: directly adding BNDChk node vs. waiting for slowPath getting to it eventually. which one is better? maybe there are difficulties in creating the exception range(s) for the metaData?

TR::Compilation *comp = cg->comp();
TR::MethodSymbol *methodSymbol = node->getSymbol()->getMethodSymbol();
static const bool disableCRC32 = feGetEnv("TR_aarch64DisableCRC32") != NULL;
static const bool disableStringIntrinsicFlagChk = feGetEnv("TR_DisableStringIntrinsicFlagChk") != NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bracket around the boolean expression is preferable and more readable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change this.

TR::RecognizedMethod rm = node->getSymbol()->castToMethodSymbol()->getMandatoryRecognizedMethod();

bool isILGenPass = !getLastRun();
static const bool disableStringIntrinsicFlagChk = feGetEnv("TR_DisableStringIntrinsicFlagChk") != NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

bool disableCAEInlining = !cg->getSupportsInlineUnsafeCompareAndExchange();
static bool disableOSW = feGetEnv("TR_noPauseOnSpinWait") != NULL;
static const bool disableStringIntrinsicFlagChk = feGetEnv("TR_DisableStringIntrinsicFlagChk") != NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

}
}

static const bool disableStringIntrinsicFlagChk = feGetEnv("TR_DisableStringIntrinsicFlagChk") != NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

bool disableCASInlining = !cg->getSupportsInlineUnsafeCompareAndSet();
bool disableCAEInlining = !cg->getSupportsInlineUnsafeCompareAndExchange();

static const bool disableStringIntrinsicFlagChk = feGetEnv("TR_DisableStringIntrinsicFlagChk") != NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

@IBMJimmyk

Copy link
Copy Markdown
Contributor Author

For the indexOf operations, we don't know in advance if an out of bounds exception will occur. For example, say the race condition triggered and the array being searched in is supposed to have 10 characters but the actual byte array really only has room for 2 characters. If the character being searched for is found in those 2 characters, it won't go out of bounds.

For the inflate operation, it is possible to know if it will go out of bounds in advance. However, the out of bounds exception may be thrown part way into the inflate operation. In this case, part of the output array will be modified before the exception is thrown. For this reason, the slow path is taken to perform the partial edit to the output array before throwing the exception.

Prior to JDK25, due to a race condition in AbstractStringBuilder, it is
possible for some accelerated String intrinsics to perform an out of
bounds array access. This applies to:

java/lang/StringLatin1.inflate([BI[CII)V
java/lang/StringLatin1.indexOf([BI[BII)I
java/lang/StringUTF16.indexOf([BI[BII)I

To address this, bound checking has been added such that the safe slow
path code is performed in the rares cases that an out of bounds array
access may occur.

Former behavior is restored via the TR_DisableStringIntrinsicFlagChk
envvar. As the problem does not exist in JDK25, the bound checking is
not added in JDK25 and onward.

Issue: eclipse-openj9#23880
Signed-off-by: jimmyk <jimmyk@ca.ibm.com>

@zl-wang zl-wang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:jit depends:omr Pull request is dependent on a corresponding change in OMR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants