Fix bug with error handling in UCS-2, UCS-4, UTF-32 decoders.
diff --git a/ChangeLog b/ChangeLog
index ffcd39b..1c40337 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-27 Bruno Haible <bruno@clisp.org>
+
+ Fix bug with error handling in UCS-2, UCS-4, UTF-32 decoders.
+ * lib/ucs2.h (ucs2_mbtowc): Increment count only after validating wc.
+ * lib/ucs4.h (ucs4_mbtowc): Likewise.
+ * lib/utf32.h (utf32_mbtowc): Likewise.
+ Reported at <https://savannah.gnu.org/bugs/?34916>.
+
2012-06-30 Bruno Haible <bruno@clisp.org>
Improve ISO-2022-CP-MS versus CP932.
diff --git a/lib/ucs2.h b/lib/ucs2.h
index 206b8cc..02c946f 100644
--- a/lib/ucs2.h
+++ b/lib/ucs2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2001, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 1999-2001, 2008, 2011 Free Software Foundation, Inc.
* This file is part of the GNU LIBICONV Library.
*
* The GNU LIBICONV Library is free software; you can redistribute it
@@ -32,7 +32,6 @@
int count = 0;
for (; n >= 2;) {
ucs4_t wc = (state ? s[0] + (s[1] << 8) : (s[0] << 8) + s[1]);
- s += 2; n -= 2; count += 2;
if (wc == 0xfeff) {
} else if (wc == 0xfffe) {
state ^= 1;
@@ -42,8 +41,9 @@
} else {
*pwc = wc;
conv->istate = state;
- return count;
+ return count+2;
}
+ s += 2; n -= 2; count += 2;
}
conv->istate = state;
return RET_TOOFEW(count);
diff --git a/lib/ucs4.h b/lib/ucs4.h
index 00d08d2..ef9da5f 100644
--- a/lib/ucs4.h
+++ b/lib/ucs4.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2001, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 1999-2001, 2008, 2011 Free Software Foundation, Inc.
* This file is part of the GNU LIBICONV Library.
*
* The GNU LIBICONV Library is free software; you can redistribute it
@@ -34,18 +34,18 @@
ucs4_t wc = (state
? s[0] + (s[1] << 8) + (s[2] << 16) + (s[3] << 24)
: (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3]);
- s += 4; n -= 4; count += 4;
if (wc == 0x0000feff) {
} else if (wc == 0xfffe0000u) {
state ^= 1;
} else if (wc <= 0x7fffffff) {
*pwc = wc;
conv->istate = state;
- return count;
+ return count+4;
} else {
conv->istate = state;
return RET_SHIFT_ILSEQ(count);
}
+ s += 4; n -= 4; count += 4;
}
conv->istate = state;
return RET_TOOFEW(count);
diff --git a/lib/utf32.h b/lib/utf32.h
index bc579ae..91ab840 100644
--- a/lib/utf32.h
+++ b/lib/utf32.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2001, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 1999-2001, 2008, 2011 Free Software Foundation, Inc.
* This file is part of the GNU LIBICONV Library.
*
* The GNU LIBICONV Library is free software; you can redistribute it
@@ -40,7 +40,6 @@
ucs4_t wc = (state
? s[0] + (s[1] << 8) + (s[2] << 16) + (s[3] << 24)
: (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3]);
- count += 4;
if (wc == 0x0000feff) {
} else if (wc == 0xfffe0000u) {
state ^= 1;
@@ -48,13 +47,13 @@
if (wc < 0x110000 && !(wc >= 0xd800 && wc < 0xe000)) {
*pwc = wc;
conv->istate = state;
- return count;
+ return count+4;
} else {
conv->istate = state;
return RET_SHIFT_ILSEQ(count);
}
}
- s += 4; n -= 4;
+ s += 4; n -= 4; count += 4;
}
conv->istate = state;
return RET_TOOFEW(count);