sR |I32 |expect_number |NN char **const pattern
#
sn |STRLEN |sv_pos_u2b_forwards|NN const U8 *const start \
- |NN const U8 *const send|STRLEN uoffset
+ |NN const U8 *const send|NN STRLEN *const uoffset
sn |STRLEN |sv_pos_u2b_midway|NN const U8 *const start \
|NN const U8 *send|STRLEN uoffset|const STRLEN uend
s |STRLEN |sv_pos_u2b_cached|NN SV *const sv|NN MAGIC **const mgp \
|NN const U8 *const start|NN const U8 *const send \
- |const STRLEN uoffset|STRLEN uoffset0|STRLEN boffset0
+ |STRLEN uoffset|STRLEN uoffset0|STRLEN boffset0
s |void |utf8_mg_pos_cache_update|NN SV *const sv|NN MAGIC **const mgp \
|const STRLEN byte|const STRLEN utf8|const STRLEN blen
s |STRLEN |sv_pos_b2u_midway|NN const U8 *const s|NN const U8 *const target \
assert(pattern)
#
-STATIC STRLEN S_sv_pos_u2b_forwards(const U8 *const start, const U8 *const send, STRLEN uoffset)
+STATIC STRLEN S_sv_pos_u2b_forwards(const U8 *const start, const U8 *const send, STRLEN *const uoffset)
__attribute__nonnull__(1)
- __attribute__nonnull__(2);
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3);
#define PERL_ARGS_ASSERT_SV_POS_U2B_FORWARDS \
- assert(start); assert(send)
+ assert(start); assert(send); assert(uoffset)
STATIC STRLEN S_sv_pos_u2b_midway(const U8 *const start, const U8 *send, STRLEN uoffset, const STRLEN uend)
__attribute__nonnull__(1)
#define PERL_ARGS_ASSERT_SV_POS_U2B_MIDWAY \
assert(start); assert(send)
-STATIC STRLEN S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start, const U8 *const send, const STRLEN uoffset, STRLEN uoffset0, STRLEN boffset0)
+STATIC STRLEN S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start, const U8 *const send, STRLEN uoffset, STRLEN uoffset0, STRLEN boffset0)
__attribute__nonnull__(pTHX_1)
__attribute__nonnull__(pTHX_2)
__attribute__nonnull__(pTHX_3)
offset. */
static STRLEN
S_sv_pos_u2b_forwards(const U8 *const start, const U8 *const send,
- STRLEN uoffset)
+ STRLEN *const uoffset_p)
{
const U8 *s = start;
+ STRLEN uoffset = *uoffset_p;
PERL_ARGS_ASSERT_SV_POS_U2B_FORWARDS;
- while (s < send && uoffset--)
+ while (s < send && uoffset) {
+ --uoffset;
s += UTF8SKIP(s);
+ }
if (s > send) {
/* This is the existing behaviour. Possibly it should be a croak, as
it's actually a bounds error */
s = send;
}
+ *uoffset_p -= uoffset;
return s - start;
}
created if necessary, and the found value offered to it for update. */
static STRLEN
S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start,
- const U8 *const send, const STRLEN uoffset,
+ const U8 *const send, STRLEN uoffset,
STRLEN uoffset0, STRLEN boffset0)
{
STRLEN boffset = 0; /* Actually always set, but let's keep gcc happy. */
uoffset - uoffset0,
(*mgp)->mg_len - uoffset0);
} else {
+ uoffset -= uoffset0;
boffset = boffset0
+ sv_pos_u2b_forwards(start + boffset0,
- send, uoffset - uoffset0);
+ send, &uoffset);
+ uoffset += uoffset0;
}
}
else if (cache[2] < uoffset) {
}
if (!found || PL_utf8cache < 0) {
- const STRLEN real_boffset
- = boffset0 + sv_pos_u2b_forwards(start + boffset0,
- send, uoffset - uoffset0);
+ STRLEN real_boffset;
+ uoffset -= uoffset0;
+ real_boffset = boffset0 + sv_pos_u2b_forwards(start + boffset0,
+ send, &uoffset);
+ uoffset += uoffset0;
if (found && PL_utf8cache < 0) {
if (real_boffset != boffset) {
}
use strict;
-plan( tests => 111 );
+plan( tests => 113 );
run_tests() unless caller;
}
}
+{
+ # RT#75898
+ is(eval { utf8::upgrade($_ = " "); index $_, " ", 72 }, -1,
+ 'UTF-8 cache handles offset beyond the end of the string');
+ $_ = "\x{100}BC";
+ is(index($_, "C", 4), -1,
+ 'UTF-8 cache handles offset beyond the end of the string');
+}
+
}