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;
+	}
 }
 
 

Reply via email to