tags 1042129 + patch thanks Upstream handled this when they upgraded Joni dependency to 2.2 on JRuby 9.4 series.
https://github.com/jruby/jruby/commit/3c94d31f1e198f294e9bfcb96b4188c315252b6b https://github.com/jruby/jruby/commit/783d14bcb140477bb2577310a90742d594a48896 See attached a fix for this issue.
diff -Nru jruby-9.3.9.0+ds/debian/changelog jruby-9.3.9.0+ds/debian/changelog --- jruby-9.3.9.0+ds/debian/changelog 2023-01-16 21:08:51.000000000 +0000 +++ jruby-9.3.9.0+ds/debian/changelog 2023-11-24 11:48:05.000000000 +0000 @@ -1,3 +1,11 @@ +jruby (9.3.9.0+ds-9~miguel1) UNRELEASED; urgency=medium + + * Fix FTBFS: adapt and backport changes from 9.4 releases + to accomodate for changes in regexp library Joni 2.2. + (Closes: #1042129) + + -- Miguel Landaeta <nomad...@debian.org> Fri, 24 Nov 2023 11:48:05 +0000 + jruby (9.3.9.0+ds-8) unstable; urgency=medium * d/tests: flag jirb test as flaky diff -Nru jruby-9.3.9.0+ds/debian/patches/0012-Use-Region-accessors-in-prep-for-privatizing-fields.patch jruby-9.3.9.0+ds/debian/patches/0012-Use-Region-accessors-in-prep-for-privatizing-fields.patch --- jruby-9.3.9.0+ds/debian/patches/0012-Use-Region-accessors-in-prep-for-privatizing-fields.patch 1970-01-01 01:00:00.000000000 +0100 +++ jruby-9.3.9.0+ds/debian/patches/0012-Use-Region-accessors-in-prep-for-privatizing-fields.patch 2023-11-24 11:48:05.000000000 +0000 @@ -0,0 +1,390 @@ +Subject: Use Region accessors in prep for privatizing fields +Forwarded: https://github.com/jruby/jruby/commit/3c94d31f1e198f294e9bfcb96b4188c315252b6b +-- +diff --git a/core/src/main/java/org/jruby/RubyMatchData.java b/core/src/main/java/org/jruby/RubyMatchData.java +index 48fa92b..87e7c9d 100644 +--- a/core/src/main/java/org/jruby/RubyMatchData.java ++++ b/core/src/main/java/org/jruby/RubyMatchData.java +@@ -175,11 +175,11 @@ public class RubyMatchData extends RubyObject { + private void updateCharOffsetOnlyOneReg(ByteList value, Encoding encoding) { + if (charOffsetUpdated) return; + +- if (charOffsets == null || charOffsets.numRegs < 1) charOffsets = new Region(1); ++ if (charOffsets == null || charOffsets.getNumRegs() < 1) charOffsets = new Region(1); + + if (encoding.maxLength() == 1) { +- charOffsets.beg[0] = begin; +- charOffsets.end[0] = end; ++ charOffsets.setBeg(0, begin); ++ charOffsets.setEnd(0, end); + charOffsetUpdated = true; + return; + } +@@ -195,14 +195,14 @@ public class RubyMatchData extends RubyObject { + updatePairs(value, encoding, pairs); + + if (begin < 0) { +- charOffsets.beg[0] = charOffsets.end[0] = -1; ++ charOffsets.setBeg(0, charOffsets.setEnd(0, -1)); + return; + } + Pair key = new Pair(); + key.bytePos = begin; +- charOffsets.beg[0] = pairs[Arrays.binarySearch(pairs, key)].charPos; ++ charOffsets.setBeg(0, pairs[Arrays.binarySearch(pairs, key)].charPos); + key.bytePos = end; +- charOffsets.end[0] = pairs[Arrays.binarySearch(pairs, key)].charPos; ++ charOffsets.setEnd(0, pairs[Arrays.binarySearch(pairs, key)].charPos); + + charOffsetUpdated = true; + } +@@ -211,14 +211,14 @@ public class RubyMatchData extends RubyObject { + if (charOffsetUpdated) return; + + final Region regs = this.regs; +- int numRegs = regs.numRegs; ++ int numRegs = regs.getNumRegs(); + +- if (charOffsets == null || charOffsets.numRegs < numRegs) charOffsets = new Region(numRegs); ++ if (charOffsets == null || charOffsets.getNumRegs() < numRegs) charOffsets = new Region(numRegs); + + if (encoding.maxLength() == 1) { + for (int i = 0; i < numRegs; i++) { +- charOffsets.beg[i] = regs.beg[i]; +- charOffsets.end[i] = regs.end[i]; ++ charOffsets.setBeg(i, regs.getBeg(i)); ++ charOffsets.setEnd(i, regs.getEnd(i)); + } + charOffsetUpdated = true; + return; +@@ -229,23 +229,23 @@ public class RubyMatchData extends RubyObject { + + int numPos = 0; + for (int i = 0; i < numRegs; i++) { +- if (regs.beg[i] < 0) continue; +- pairs[numPos++].bytePos = regs.beg[i]; +- pairs[numPos++].bytePos = regs.end[i]; ++ if (regs.getBeg(i) < 0) continue; ++ pairs[numPos++].bytePos = regs.getBeg(i); ++ pairs[numPos++].bytePos = regs.getEnd(i); + } + + updatePairs(value, encoding, pairs); + + Pair key = new Pair(); +- for (int i = 0; i < regs.numRegs; i++) { +- if (regs.beg[i] < 0) { +- charOffsets.beg[i] = charOffsets.end[i] = -1; ++ for (int i = 0; i < regs.getNumRegs(); i++) { ++ if (regs.getBeg(i) < 0) { ++ charOffsets.setBeg(i, charOffsets.setEnd(i, -1)); + continue; + } +- key.bytePos = regs.beg[i]; +- charOffsets.beg[i] = pairs[Arrays.binarySearch(pairs, key)].charPos; +- key.bytePos = regs.end[i]; +- charOffsets.end[i] = pairs[Arrays.binarySearch(pairs, key)].charPos; ++ key.bytePos = regs.getBeg(i); ++ charOffsets.setBeg(i, pairs[Arrays.binarySearch(pairs, key)].charPos); ++ key.bytePos = regs.getEnd(i); ++ charOffsets.setEnd(i, pairs[Arrays.binarySearch(pairs, key)].charPos); + } + + charOffsetUpdated = true; +@@ -314,13 +314,13 @@ public class RubyMatchData extends RubyObject { + return runtime.newArray( ss.infectBy(this) ); + } + } else { +- RubyArray arr = RubyArray.newBlankArray(runtime, regs.numRegs - start); ++ RubyArray arr = RubyArray.newBlankArray(runtime, regs.getNumRegs() - start); + int index = 0; +- for (int i=start; i < regs.numRegs; i++) { +- if (regs.beg[i] == -1) { ++ for (int i=start; i < regs.getNumRegs(); i++) { ++ if (regs.getBeg(i) == -1) { + arr.storeInternal(index++, nil); + } else { +- RubyString ss = makeShared(runtime, str, regs.beg[i], regs.end[i] - regs.beg[i]); ++ RubyString ss = makeShared(runtime, str, regs.getBeg(i), regs.getEnd(i) - regs.getBeg(i)); + arr.storeInternal(index++, ss.infectBy(this)); + } + } +@@ -375,7 +375,7 @@ public class RubyMatchData extends RubyObject { + result.cat((byte)'#').cat((byte)'<'); + result.append(getMetaClass().getRealClass().to_s()); + +- NameEntry[] names = new NameEntry[regs == null ? 1 : regs.numRegs]; ++ NameEntry[] names = new NameEntry[regs == null ? 1 : regs.getNumRegs()]; + + final Regex pattern = getPattern(); + for (Iterator<NameEntry> i = pattern.namedBackrefIterator(); i.hasNext();) { +@@ -520,7 +520,7 @@ public class RubyMatchData extends RubyObject { + private IRubyObject matchArySubseq(ThreadContext context, int beg, int len, RubyArray result) { + assert result != null; + +- int olen = regs.numRegs; ++ int olen = regs.getNumRegs(); + int wantedEnd = beg + len; + int j, end = olen < wantedEnd ? olen : wantedEnd; + +@@ -542,7 +542,7 @@ public class RubyMatchData extends RubyObject { + // MRI: match_ary_aref + private IRubyObject matchAryAref(ThreadContext context, IRubyObject index, RubyArray result) { + int[] begLen = new int[2]; +- int numRegs = regs.numRegs; ++ int numRegs = regs.getNumRegs(); + + /* check if idx is Range */ + IRubyObject isRange = RubyRange.rangeBeginLength(context, index, numRegs, begLen, 1); +@@ -612,7 +612,7 @@ public class RubyMatchData extends RubyObject { + public IRubyObject size(ThreadContext context) { + check(); + Ruby runtime = context.runtime; +- return regs == null ? RubyFixnum.one(runtime) : RubyFixnum.newFixnum(runtime, regs.numRegs); ++ return regs == null ? RubyFixnum.one(runtime) : RubyFixnum.newFixnum(runtime, regs.getNumRegs()); + } + + /** +@@ -624,17 +624,17 @@ public class RubyMatchData extends RubyObject { + final Ruby runtime = context.runtime; + final int i = backrefNumber(runtime, index); + +- if (i < 0 || (regs == null ? 1 : regs.numRegs) <= i) { ++ if (i < 0 || (regs == null ? 1 : regs.getNumRegs()) <= i) { + throw runtime.newIndexError("index " + i + " out of matches"); + } + +- int b = regs == null ? begin : regs.beg[i]; ++ int b = regs == null ? begin : regs.getBeg(i); + + if (b < 0) return context.nil; + + updateCharOffset(); + +- return RubyFixnum.newFixnum(runtime, charOffsets.beg[i]); ++ return RubyFixnum.newFixnum(runtime, charOffsets.getBeg(i)); + } + + /** match_end +@@ -647,17 +647,17 @@ public class RubyMatchData extends RubyObject { + final Ruby runtime = context.runtime; + final int i = backrefNumber(runtime, index); + +- if (i < 0 || (regs == null ? 1 : regs.numRegs) <= i) { ++ if (i < 0 || (regs == null ? 1 : regs.getNumRegs()) <= i) { + throw runtime.newIndexError("index " + i + " out of matches"); + } + +- int e = regs == null ? end : regs.end[i]; ++ int e = regs == null ? end : regs.getEnd(i); + + if (e < 0) return context.nil; + + if ( ! str.singleByteOptimizable() ) { + updateCharOffset(); +- e = charOffsets.end[i]; ++ e = charOffsets.getEnd(i); + } + + return RubyFixnum.newFixnum(runtime, e); +@@ -677,7 +677,7 @@ public class RubyMatchData extends RubyObject { + final Ruby runtime = context.runtime; + final int i = backrefNumber(runtime, index); + +- if (i < 0 || (regs == null ? 1 : regs.numRegs) <= i) { ++ if (i < 0 || (regs == null ? 1 : regs.getNumRegs()) <= i) { + throw runtime.newIndexError("index " + i + " out of matches"); + } + +@@ -686,16 +686,16 @@ public class RubyMatchData extends RubyObject { + b = begin; + e = end; + } else { +- b = regs.beg[i]; +- e = regs.end[i]; ++ b = regs.getBeg(i); ++ e = regs.getEnd(i); + } + + if (b < 0) return runtime.newArray(context.nil, context.nil); + + if ( ! str.singleByteOptimizable() ) { + updateCharOffset(); +- b = charOffsets.beg[i]; +- e = charOffsets.end[i]; ++ b = charOffsets.getBeg(i); ++ e = charOffsets.getEnd(i); + } + + return runtime.newArray(RubyFixnum.newFixnum(runtime, b), RubyFixnum.newFixnum(runtime, e)); +@@ -833,8 +833,8 @@ public class RubyMatchData extends RubyObject { + if (i > 1) return -1; + return begin; + } +- if (i > regs.numRegs) return -1; +- return regs.beg[i]; ++ if (i > regs.getNumRegs()) return -1; ++ return regs.getBeg(i); + } + + /** +@@ -848,8 +848,8 @@ public class RubyMatchData extends RubyObject { + if (i > 1) return -1; + return end; + } +- if (i > regs.numRegs) return -1; +- return regs.end[i]; ++ if (i > regs.getNumRegs()) return -1; ++ return regs.getEnd(i); + } + + /** +@@ -858,7 +858,7 @@ public class RubyMatchData extends RubyObject { + * @return the number of regions in this match + */ + public int numRegs() { +- return regs == null ? 1 : regs.numRegs; ++ return regs == null ? 1 : regs.getNumRegs(); + } + + @Deprecated +diff --git a/core/src/main/java/org/jruby/RubyRegexp.java b/core/src/main/java/org/jruby/RubyRegexp.java +index 66852ee..229895f 100755 +--- a/core/src/main/java/org/jruby/RubyRegexp.java ++++ b/core/src/main/java/org/jruby/RubyRegexp.java +@@ -1588,11 +1588,11 @@ public class RubyRegexp extends RubyObject implements ReOptions, EncodingCapable + start = match.begin; + end = match.end; + } else { +- if (nth >= match.regs.numRegs || (nth < 0 && (nth+=match.regs.numRegs) <= 0)) { ++ if (nth >= match.regs.getNumRegs() || (nth < 0 && (nth+=match.regs.getNumRegs()) <= 0)) { + return match.getRuntime().getNil(); + } +- start = match.regs.beg[nth]; +- end = match.regs.end[nth]; ++ start = match.regs.getBeg(nth); ++ end = match.regs.getEnd(nth); + } + + if (start == -1) return match.getRuntime().getNil(); +@@ -1643,10 +1643,10 @@ public class RubyRegexp extends RubyObject implements ReOptions, EncodingCapable + RubyMatchData m = (RubyMatchData) match; + m.check(); + +- if (m.regs == null || m.regs.beg[0] == -1) return m.getRuntime().getNil(); ++ if (m.regs == null || m.regs.getBeg(0) == -1) return m.getRuntime().getNil(); + + int i; +- for (i = m.regs.numRegs - 1; m.regs.beg[i] == -1 && i > 0; i--); ++ for (i = m.regs.getNumRegs() - 1; m.regs.getBeg(i) == -1 && i > 0; i--) + if (i == 0) return m.getRuntime().getNil(); + + return nth_match(i, m); +@@ -1757,8 +1757,8 @@ public class RubyRegexp extends RubyObject implements ReOptions, EncodingCapable + continue; + case '+': + if (regs != null) { +- no = regs.numRegs - 1; +- while (regs.beg[no] == -1 && no > 0) no--; ++ no = regs.getNumRegs() - 1; ++ while (regs.getBeg(no) == -1 && no > 0) no--; + } + if (no == 0) continue; + break; +@@ -1772,9 +1772,9 @@ public class RubyRegexp extends RubyObject implements ReOptions, EncodingCapable + + if (regs != null) { + if (no >= 0) { +- if (no >= regs.numRegs) continue; +- if (regs.beg[no] == -1) continue; +- EncodingUtils.encStrBufCat(runtime, val, srcbs.getUnsafeBytes(), srcbs.getBegin() + regs.beg[no], regs.end[no] - regs.beg[no], srcEnc); ++ if (no >= regs.getNumRegs()) continue; ++ if (regs.getBeg(no) == -1) continue; ++ EncodingUtils.encStrBufCat(runtime, val, srcbs.getUnsafeBytes(), srcbs.getBegin() + regs.getBeg(no), regs.getEnd(no) - regs.getBeg(no), srcEnc); + } + } else { + if (no != 0 || begin == -1) continue; +diff --git a/core/src/main/java/org/jruby/RubyString.java b/core/src/main/java/org/jruby/RubyString.java +index 98c470c..a8a468e 100644 +--- a/core/src/main/java/org/jruby/RubyString.java ++++ b/core/src/main/java/org/jruby/RubyString.java +@@ -3843,7 +3843,7 @@ public class RubyString extends RubyObject implements CharSequence, EncodingCapa + } + + private int subpatSetCheck(Ruby runtime, int nth, Region regs) { +- int numRegs = regs == null ? 1 : regs.numRegs; ++ int numRegs = regs == null ? 1 : regs.getNumRegs(); + if (nth < numRegs) { + if (nth < 0) { + if (-nth < numRegs) return nth + numRegs; +@@ -3871,8 +3871,8 @@ public class RubyString extends RubyObject implements CharSequence, EncodingCapa + start = match.begin; + end = match.end; + } else { +- start = match.regs.beg[nth]; +- end = match.regs.end[nth]; ++ start = match.regs.getBeg(nth); ++ end = match.regs.getEnd(nth); + } + if (start == -1) throw runtime.newIndexError("regexp group " + nth + " not matched"); + RubyString replStr = repl.convertToString(); +diff --git a/core/src/main/java/org/jruby/ext/strscan/RubyStringScanner.java b/core/src/main/java/org/jruby/ext/strscan/RubyStringScanner.java +index ac49149..c04ba7c 100644 +--- a/core/src/main/java/org/jruby/ext/strscan/RubyStringScanner.java ++++ b/core/src/main/java/org/jruby/ext/strscan/RubyStringScanner.java +@@ -282,8 +282,8 @@ public class RubyStringScanner extends RubyObject { + this.beg = matcher.getBegin(); + this.end = matcher.getEnd(); + } else { +- this.beg = regs.beg[0]; +- this.end = regs.end[0]; ++ this.beg = regs.getBeg(0); ++ this.end = regs.getEnd(0); + } + + if (ret < 0) return context.nil; +@@ -524,7 +524,7 @@ public class RubyStringScanner extends RubyObject { + if (pattern == null) return context.nil; + } + int i = RubyMatchData.backrefNumber(runtime, pattern, regs, idx); +- int numRegs = regs == null ? 1 : regs.numRegs; ++ int numRegs = regs == null ? 1 : regs.getNumRegs(); + + if (i < 0) i += numRegs; + if (i < 0 || i >= numRegs) { +@@ -536,8 +536,8 @@ public class RubyStringScanner extends RubyObject { + if (beg == -1) return context.nil; + return extractRange(runtime, lastPos + beg, lastPos + end); + } else { +- if (regs.beg[i] == -1) return context.nil; +- return extractRange(context.runtime, lastPos + regs.beg[i], lastPos + regs.end[i]); ++ if (regs.getBeg(i) == -1) return context.nil; ++ return extractRange(context.runtime, lastPos + regs.getBeg(i), lastPos + regs.getEnd(i)); + } + } + +@@ -633,7 +633,7 @@ public class RubyStringScanner extends RubyObject { + @JRubyMethod(name = "size") + public IRubyObject size(ThreadContext context) { + if (!isMatched()) return context.nil; +- return context.runtime.newFixnum(regs.numRegs); ++ return context.runtime.newFixnum(regs.getNumRegs()); + } + + @JRubyMethod(name = "captures") +@@ -645,12 +645,12 @@ public class RubyStringScanner extends RubyObject { + + Ruby runtime = context.runtime; + +- numRegs = regs.numRegs; ++ numRegs = regs.getNumRegs(); + newAry = RubyArray.newArray(runtime, numRegs); + + for (i = 1; i < numRegs; i++) { +- IRubyObject str = extractRange(runtime, lastPos + regs.beg[i], +- lastPos + regs.end[i]); ++ IRubyObject str = extractRange(runtime, lastPos + regs.getBeg(i), ++ lastPos + regs.getEnd(i)); + newAry.push(str); + } + diff -Nru jruby-9.3.9.0+ds/debian/patches/0013-Use-Region-factory-method-to-avoid-coupling.patch jruby-9.3.9.0+ds/debian/patches/0013-Use-Region-factory-method-to-avoid-coupling.patch --- jruby-9.3.9.0+ds/debian/patches/0013-Use-Region-factory-method-to-avoid-coupling.patch 1970-01-01 01:00:00.000000000 +0100 +++ jruby-9.3.9.0+ds/debian/patches/0013-Use-Region-factory-method-to-avoid-coupling.patch 2023-11-24 11:48:05.000000000 +0000 @@ -0,0 +1,25 @@ +Subject: Use Region factory method to avoid coupling +Forwarded: https://github.com/jruby/jruby/commit/783d14bcb140477bb2577310a90742d594a48896 +-- +diff --git a/core/src/main/java/org/jruby/RubyMatchData.java b/core/src/main/java/org/jruby/RubyMatchData.java +index 87e7c9d..ccc5294 100644 +--- a/core/src/main/java/org/jruby/RubyMatchData.java ++++ b/core/src/main/java/org/jruby/RubyMatchData.java +@@ -175,7 +175,7 @@ public class RubyMatchData extends RubyObject { + private void updateCharOffsetOnlyOneReg(ByteList value, Encoding encoding) { + if (charOffsetUpdated) return; + +- if (charOffsets == null || charOffsets.getNumRegs() < 1) charOffsets = new Region(1); ++ if (charOffsets == null || charOffsets.getNumRegs() < 1) charOffsets = Region.newRegion(1); + + if (encoding.maxLength() == 1) { + charOffsets.setBeg(0, begin); +@@ -213,7 +213,7 @@ public class RubyMatchData extends RubyObject { + final Region regs = this.regs; + int numRegs = regs.getNumRegs(); + +- if (charOffsets == null || charOffsets.getNumRegs() < numRegs) charOffsets = new Region(numRegs); ++ if (charOffsets == null || charOffsets.getNumRegs() < numRegs) charOffsets = Region.newRegion(numRegs); + + if (encoding.maxLength() == 1) { + for (int i = 0; i < numRegs; i++) { diff -Nru jruby-9.3.9.0+ds/debian/patches/series jruby-9.3.9.0+ds/debian/patches/series --- jruby-9.3.9.0+ds/debian/patches/series 2023-01-16 21:08:51.000000000 +0000 +++ jruby-9.3.9.0+ds/debian/patches/series 2023-11-24 11:48:05.000000000 +0000 @@ -9,3 +9,5 @@ 0010-Fix-test-failures-related-to-Module-PTY.patch 0011-Remove-failing-test-in-build-environment.patch 0011-Fix-intermittent-mri-core-test-failure.patch +0012-Use-Region-accessors-in-prep-for-privatizing-fields.patch +0013-Use-Region-factory-method-to-avoid-coupling.patch