Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libedit From Ingo Schwarze:



details:   https://anonhg.NetBSD.org/src/rev/b478533402dd
branches:  trunk
changeset: 813697:b478533402dd
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Feb 14 17:06:24 2016 +0000

description:
>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.

diffstat:

 lib/libedit/chartype.h |   4 +++-
 lib/libedit/eln.c      |  21 +++++++++++++++------
 2 files changed, 18 insertions(+), 7 deletions(-)

diffs (72 lines):

diff -r 3f1773b96c93 -r b478533402dd lib/libedit/chartype.h
--- a/lib/libedit/chartype.h    Sun Feb 14 14:49:34 2016 +0000
+++ b/lib/libedit/chartype.h    Sun Feb 14 17:06:24 2016 +0000
@@ -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 @@
 #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))
diff -r 3f1773b96c93 -r b478533402dd lib/libedit/eln.c
--- a/lib/libedit/eln.c Sun Feb 14 14:49:34 2016 +0000
+++ b/lib/libedit/eln.c Sun Feb 14 17:06:24 2016 +0000
@@ -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 @@
        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;
+       }
 }
 
 



Home | Main Index | Thread Index | Old Index