summaryrefslogtreecommitdiff
path: root/pp_sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'pp_sys.c')
-rw-r--r--pp_sys.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/pp_sys.c b/pp_sys.c
index ea35136f8e..ed7030700a 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1517,6 +1517,9 @@ PP(pp_sysread)
int fp_utf8;
Size_t got = 0;
Size_t wanted;
+ bool charstart = NULL;
+ STRLEN skip;
+ STRLEN charskip;
gv = (GV*)*++MARK;
if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD)
@@ -1563,6 +1566,9 @@ PP(pp_sysread)
DIE(aTHX_ "Negative length");
wanted = length;
+ charstart = TRUE;
+ charskip = 0;
+
#ifdef HAS_SOCKET
if (PL_op->op_type == OP_RECV) {
char namebuf[MAXPATHLEN];
@@ -1683,23 +1689,30 @@ PP(pp_sysread)
/* Look at utf8 we got back and count the characters */
char *bend = buffer + count;
while (buffer < bend) {
- STRLEN skip = UTF8SKIP(buffer);
- if (buffer+skip > bend) {
+ if (charstart) {
+ skip = UTF8SKIP(buffer);
+ charskip = 0;
+ }
+ if (buffer - charskip + skip > bend) {
/* partial character - try for rest of it */
length = skip - (bend-buffer);
offset = bend - SvPVX(bufsv);
+ charstart = FALSE;
+ charskip += count;
goto more_bytes;
}
else {
got++;
buffer += skip;
+ charstart = TRUE;
+ charskip = 0;
}
}
/* If we have not 'got' the number of _characters_ we 'wanted' get some more
provided amount read (count) was what was requested (length)
*/
if (got < wanted && count == length) {
- length = (wanted-got);
+ length = wanted - got;
offset = bend - SvPVX(bufsv);
goto more_bytes;
}