Skip to content

Commit 7b77f30

Browse files
committed
Fix charpos when the stored string is shrunk
1 parent 435095d commit 7b77f30

4 files changed

Lines changed: 18 additions & 4 deletions

File tree

ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,12 @@ public IRubyObject charpos(ThreadContext context) {
236236

237237
ByteList strBL = str.getByteList();
238238
int strBeg = strBL.begin();
239+
int strSize = strBL.getRealSize();
240+
int pos = curr;
241+
242+
if (pos > strSize) pos = strSize;
239243

240-
return runtime.newFixnum(StringSupport.strLength(strBL.getEncoding(), strBL.unsafeBytes(), strBeg, strBeg + curr));
244+
return runtime.newFixnum(StringSupport.strLength(strBL.getEncoding(), strBL.unsafeBytes(), strBeg, strBeg + pos));
241245
}
242246

243247
private IRubyObject extractRange(Ruby runtime, int beg, int end) {

ext/strscan/strscan.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct strscanner
7979
#define CURPTR(s) (S_PBEG(s) + (s)->curr)
8080
#define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
8181

82-
#define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str))
82+
#define EOS_P(s) ((s)->curr >= RSTRING_LEN((s)->str))
8383

8484
#define GET_SCANNER(obj,var) do {\
8585
(var) = check_strscan(obj);\
@@ -573,10 +573,12 @@ static VALUE
573573
strscan_get_charpos(VALUE self)
574574
{
575575
struct strscanner *p;
576+
const char *s;
576577

577578
GET_SCANNER(self, p);
578579

579-
return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str)));
580+
s = EOS_P(p) ? S_PEND(p) : CURPTR(p);
581+
return LONG2NUM(rb_enc_strlen(S_PBEG(p), s, rb_enc_get(p->str)));
580582
}
581583

582584
/*

lib/strscan/truffleruby.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def pos=(new_pos)
5959
end
6060
alias_method :pointer=, :pos=
6161

62-
def charpos = Primitive.string_byte_index_to_character_index(@string, @pos)
62+
def charpos = (eos? ? @string.size : Primitive.string_byte_index_to_character_index(@string, @pos))
6363

6464
def rest = @string.byteslice(@pos, @string.bytesize)
6565

test/strscan/test_stringscanner.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,14 @@ class << string
231231
assert_equal(8, scanner.charpos)
232232
end
233233

234+
def test_charpos_when_shrunk
235+
s = "\u{e9}" * 64
236+
sc = StringScanner.new(s)
237+
sc.scan(/(?:\u{e9})+/)
238+
s.replace("z")
239+
assert_equal(s.length, sc.charpos)
240+
end
241+
234242
def test_concat
235243
s = create_string_scanner('a'.dup)
236244
s.scan(/a/)

0 commit comments

Comments
 (0)