Project

General

Profile

Actions

Bug #1594

closed

strxfrm may write past the specified buffer

Added by Rich Lowe over 9 years ago. Updated over 9 years ago.

Status:
Resolved
Priority:
High
Category:
lib - userland libraries
Start date:
2011-10-04
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

Theo reports


#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <locale.h>

int main() {
  int size, nsize;
  char locale[128];
  unsigned char in[2] = { 0337, 0 };
  char *mout, *out, after, before;
  while(fgets(locale, sizeof(locale), stdin) != NULL) {
    locale[strlen(locale)-1] = '\0';
    printf("locale -> %s\n", locale);
    setlocale(LC_COLLATE, locale);
    size = strxfrm(NULL, (const char *)in, 0);

    printf("Wants %d\nLet's allocate only %d\n", size + 1, size);
    mout = malloc(size+2);
    out = mout + 1;
    /* This is an intentional illegal access */
    after = out[size];
    before = mout[0];
    nsize = strxfrm(out, (const char *)in, size);
    printf("srrxfrm -> %d\n", nsize);
    printf("clobbered the byte before? %d == %d?\n", before, mout[0]);
    printf("clobbered the byte after? %d == %d?\n", after, out[size]);
    if(before != mout[0] || after != out[size]) abort();
  }
}

aborts when the specified locale is el_GR.ISO8859-7

metropolis:~> echo el_GR.ISO8859-7 | ./foo
locale -> el_GR.ISO8859-7
Wants 2
Let's allocate only 1
srrxfrm -> 1
clobbered the byte before? -33 == -33?
clobbered the byte after? 0 == 46?
zsh: done                           echo el_GR.ISO8859-7 | 
zsh: IOT instruction (core dumped)  ./foo

He proposes

diff -r da58f9d4ef03 usr/src/lib/libc/port/locale/collate.c
--- a/usr/src/lib/libc/port/locale/collate.c    Mon Aug 22 11:37:10 2011 -0400
+++ b/usr/src/lib/libc/port/locale/collate.c    Tue Oct 04 07:38:45 2011 -0700
@@ -588,9 +588,10 @@
                                if (room) {
                                        while (b) {
                                                b--;
-                                               if (room)
+                                               if (room) {
                                                        *xf++ = buf[b];
-                                               room--;
+                                                       room--;
+                                               }
                                        }
                                }
                                need = want;
@@ -613,9 +614,10 @@

                                        while (b) {
                                                b--;
-                                               if (room)
+                                               if (room) {
                                                        *xf++ = buf[b];
-                                               room--;
+                                                       room--;
+                                               }
                                        }
                                }
                                need = want;

as a fix.

I (separately) am also suspicious by the length returned. On the mac, we think this will require 13 bytes, rather than 2.

Also, and perhaps relatedly in strxfrm slen is in units of sizeof(wchar_t), surely the return should multiply so it's in bytes as returned? But maybe not, I'm tired.

Actions

Also available in: Atom PDF