From: Gabriel Ivăncescu Subject: [PATCH v2 2/2] libs/port/mbtowc: Convert 1 character at a time if dst overlaps into src Message-Id: <567f6efa307f60fa63793a386e3de8689198e63c.1535455721.git.gabrielopcode@gmail.com> Date: Tue, 28 Aug 2018 14:29:49 +0300 In-Reply-To: <765a264edbcdad54e54e638f21ac5f5e12bdbf29.1535455721.git.gabrielopcode@gmail.com> References: <765a264edbcdad54e54e638f21ac5f5e12bdbf29.1535455721.git.gabrielopcode@gmail.com> Some applications partially overlap the two buffers. For such rare corner cases, do a single check so that there will be no performance regressions, as unsigned operations are defined to wrap around. Bug discovered by Jason Edmeades, revised from bug report. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38558 Signed-off-by: Gabriel Ivăncescu --- libs/port/mbtowc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/port/mbtowc.c b/libs/port/mbtowc.c index 4977c82..6ed2c2e 100644 --- a/libs/port/mbtowc.c +++ b/libs/port/mbtowc.c @@ -65,6 +65,17 @@ static inline int mbstowcs_sbcs( const struct sbcs_table *table, int flags, ret = -1; } + /* dst can overlap into src, in which case we need to handle 1 char at a time, + but when src < dst, there is no issue no matter how many we handle at once */ + if ((UINT_PTR) ((UINT_PTR)src - (UINT_PTR)dst) < srclen * sizeof(*dst)) + { + do + *dst++ = cp2uni[*src++]; + while (--srclen); + return ret; + } + + /* dst doesn't overlap into src */ for (;;) { switch(srclen) -- 1.9.1