Module Name: src
Committed By: christos
Date: Sun Feb 14 17:06:24 UTC 2016
Modified Files:
src/lib/libedit: chartype.h eln.c
Log Message:
>From Ingo Schwarze:
el_getc() for the WIDECHAR case, that is, the version in eln.c.
For a UTF-8 locale, it is broken in four ways:
1. If the character read is outside the ASCII range, the function
does an undefined cast from wchar_t to char. Even if wchar_t
is internally represented as UCS-4, that is wrong and dangerous
because characters beyond codepoint U+0255 get their high bits
truncated, meaning that perfectly valid printable Unicode
characters get mapped to arbitrary bytes, even the ASCII escape
character for some Unicode characters. But wchar_t need not
be implemented in terms of UCS-4, so the outcome of this function
is undefined for any and all input.
2. If insufficient space is available for the result, the function
fails to detect failure and returns garbage rather than -1 as
specified in the documentation.
3. The documentation says that errno will be set on failure, but
that doesn't happen either in the above case.
4. Even for ASCII characters, the results may be wrong if wchar_t
is not using UCS-4.
To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/lib/libedit/chartype.h
cvs rdiff -u -r1.21 -r1.22 src/lib/libedit/eln.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libedit/chartype.h
diff -u src/lib/libedit/chartype.h:1.19 src/lib/libedit/chartype.h:1.20
--- src/lib/libedit/chartype.h:1.19 Sun Feb 14 09:49:34 2016
+++ src/lib/libedit/chartype.h Sun Feb 14 12:06:24 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: chartype.h,v 1.19 2016/02/14 14:49:34 christos Exp $ */
+/* $NetBSD: chartype.h,v 1.20 2016/02/14 17:06:24 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -61,6 +61,7 @@
#endif
#define ct_mbrtowc mbrtowc
+#define ct_wctob wctob
#define ct_wctomb wctomb
#define ct_wctomb_reset wctomb(0,0)
#define ct_wcstombs wcstombs
@@ -113,6 +114,7 @@ Width(wchar_t c)
#else /* NARROW */
size_t ct_mbrtowc(char *, const char *, size_t, void *);
+#define ct_wctob(w) ((int)(w))
#define ct_wctomb error
#define ct_wctomb_reset
#define ct_wcstombs(a, b, c) (strncpy(a, b, c), strlen(a))
Index: src/lib/libedit/eln.c
diff -u src/lib/libedit/eln.c:1.21 src/lib/libedit/eln.c:1.22
--- src/lib/libedit/eln.c:1.21 Fri Feb 12 12:23:21 2016
+++ src/lib/libedit/eln.c Sun Feb 14 12:06:24 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: eln.c,v 1.21 2016/02/12 17:23:21 christos Exp $ */
+/* $NetBSD: eln.c,v 1.22 2016/02/14 17:06:24 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -34,12 +34,13 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: eln.c,v 1.21 2016/02/12 17:23:21 christos Exp $");
+__RCSID("$NetBSD: eln.c,v 1.22 2016/02/14 17:06:24 christos Exp $");
#endif /* not lint && not SCCSID */
#include "histedit.h"
#include "el.h"
#include "read.h"
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -50,10 +51,18 @@ el_getc(EditLine *el, char *cp)
int num_read;
wchar_t wc = 0;
- num_read = el_wgetc (el, &wc);
- if (num_read > 0)
- *cp = (char)wc;
- return num_read;
+ num_read = el_wgetc(el, &wc);
+ *cp = '\0';
+ if (num_read <= 0)
+ return num_read;
+ num_read = ct_wctob(wc);
+ if (num_read == EOF) {
+ errno = ERANGE;
+ return -1;
+ } else {
+ *cp = (char)num_read;
+ return 1;
+ }
}