Project

General

Profile

Bug #1046

wcsxfrm(3C) crashes when len arg is 0

Added by Gordon Ross over 9 years ago. Updated over 9 years ago.

Status:
Resolved
Priority:
High
Assignee:
-
Category:
lib - userland libraries
Start date:
2011-05-17
Due date:
% Done:

0%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

Get a core dump from sort after:

LANG=en_US.UTF-8
LC_COLLATE=C
find . -name '*.[ch]' |sort
ksh: 1855: Memory fault(coredump)
$ mdb core
Loading modules: [ libc.so.1 ld.so.1 ]

$C

fffffd7fffdff660 libc.so.1`wcsncpy+0xf()
fffffd7fffdff690 libc.so.1`wcsxfrm+0x80()
fffffd7fffdff700 field_convert_alpha_wide+0x2d6()
fffffd7fffdff760 field_convert_wide+0x17b()
fffffd7fffdff7c0 stream_insert+0xa8()
fffffd7fffdff830 internal_sort+0x19e()
fffffd7fffdff850 main+0x6a()
fffffd7fffdff860 0x40639c()

#1

Updated by Rich Lowe over 9 years ago

  • Subject changed from ksh core dump with LANG=en_US.UTF-8 LC_COLLATE=C ... to wcsxfrm(3C) crashes when len arg is 0
  • Tags deleted (needs-triage)

This is a bug in wcsxfrm it can be reproduced with this code:


#include <stdio.h>
#include <wchar.h>

int
main(int argc, char **argv) 
{
        wchar_t *f = L"Foo";
        int n;
        n = wcsxfrm(NULL, f, 0);
        exit(0);
}

We crash like this:

 feeb42ca wcsncpy  (0, 8050d8c, ffffffff, feecf236) + 22
 feecf2b8 wcsxfrm  (0, 8050d8c, 0, fee6ea42) + 90
 08050d0a main     (1, 8047de8, 8047df0, feffbafc, 8047ddc, 8050b1a) + 32
 08050b7b _start   (1, 8047e9c, 0, 8047ea2, 8047eae, 8047ebc) + 83

Because wcsxfrm underflows a size_t here source:usr/src/lib/libc/port/locale/wcsxfrm.c#L69

A length of 0 and NULL first argument are documented to be acceptable:

If n is 0, ws1  is permitted  to  be  a  null  pointer.
-- wcsxfrm(3C)
#2

Updated by Gordon Ross over 9 years ago

This fixes it for me:

diff -r 5e6d930c0c9b usr/src/lib/libc/port/locale/wcsxfrm.c
--- a/usr/src/lib/libc/port/locale/wcsxfrm.c    Tue May 17 12:36:01 2011 -0400
+++ b/usr/src/lib/libc/port/locale/wcsxfrm.c    Wed May 18 23:38:10 2011 -0400
@@ -65,7 +65,7 @@
     slen = wcslen(src);
     if (slen < len)
         (void) wcscpy(dest, src);
-    else {
+    else if (len) {
         (void) wcsncpy(dest, src, len - 1);
         dest[len - 1] = L'\0';
     }

#3

Updated by Gordon Ross over 9 years ago

  • Priority changed from Normal to High
#4

Updated by Jason King over 9 years ago

Minor style nit, would 'else if (len != 0) {' be preferred since it's not a boolean?

#5

Updated by Gordon Ross over 9 years ago

  • Status changed from New to Resolved

changeset: 13376:c3f168efd1e4
tag: tip
user: Gordon Ross <>
date: Thu May 19 13:45:25 2011 -0400

description:
1046 wcsxfrm(3C) crashes when len arg is 0
Reviewed by: Robert Gordon <>
Reviewed by: Jason King <>
Reviewed by: Garrett D'Amore <>
Approved by: Albert Lee <>

modified:
usr/src/lib/libc/port/locale/wcsxfrm.c

Also available in: Atom PDF