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

Bug#517625: libc6-dev: compile() in obsolete <regexp.h> returns incorrect values wrt SUSv2



Package: libc6-dev
Version: 2.7-16
Severity: normal
File: /usr/include/regexp.h

According to SUSv2, compile() defined in <regexp.h> must invoke
RETURN(ptr) if it succeeds or ERROR(val) if it fails.  The
current implementation in glibc violates the standard in two
ways:

(1) It often invokes RETURN in error situations.  For example, it
    maps REG_EBRACE to RETURN(44).  That should be ERROR(44)
    instead.

(2) If it succeeds, it invokes RETURN with a pointer that points
    outside the buffer provided by the caller.  It should have
    placed the compiled regexp object at the beginning of the
    buffer and given to RETURN a pointer just beyond the end of
    the object.  SUSv2 says the pointer is useful for memory
    allocation; presumably, an application could use the
    remaining part of the buffer for other purposes.  The
    application cannot do that when the pointer points somewhere
    else entirely.  It seems compile() actually sets up
    __expr_ptr->buffer and __expr_ptr->allocated in order to tell
    regcomp() where it should place the compiled data, but
    regcomp() then clears those members right away and allocates
    its own buffer.

With bugs like this, it may be better to remove <regexp.h> than
fix it.

#include <stdio.h>

static char *arg_of_RETURN;
static int arg_of_ERROR;
static int fail;
static char is_RETURN;
static char is_ERROR;

#define INIT	const unsigned char *re = (unsigned char *) instring;
#define GETC()	(*re++)
#define PEEKC() (*re)
#define UNGETC(c)						 \
	do {							 \
		int ch = (c);					 \
		--re;						 \
		if (ch != *re) {				 \
			printf("FAIL: UNGETC(%d) expected %d\n", \
			       ch, *re);			 \
			fail++;					 \
		}						 \
	} while (0)
#define RETURN(ptr) return (arg_of_RETURN = (ptr), arg_of_ERROR = 0, &is_RETURN)
#define ERROR(val) return (arg_of_RETURN = NULL, arg_of_ERROR = (val), &is_ERROR)

#include <regexp.h>

int
main(void)
{
	enum { buflen = 100000 };
	char expbuf[buflen];
	char *ptr;
	int totalfail = 0;

	printf("TEST: compile regexp to one-byte buffer\n");
	fail = 0;
	ptr = compile("tropelet", expbuf, expbuf + 1, 'e');
	if (ptr != &is_ERROR) {
		printf("FAIL: compile did not use ERROR\n");
		fail++;
	} else if (arg_of_ERROR != 50) {
		printf("FAIL: compile used ERROR(%d), not ERROR(50)\n",
		       arg_of_ERROR);
		fail++;
	}
	if (fail)
		totalfail++;
	else
		printf("OK\n");

	printf("TEST: compile regexp to large buffer\n");
	fail = 0;
	ptr = compile("tropelet", expbuf, expbuf + buflen, 'e');
	if (ptr != &is_RETURN) {
		printf("FAIL: compile did not use RETURN\n");
		fail++;
	} else if (arg_of_RETURN < expbuf || arg_of_RETURN > expbuf + buflen) {
		printf("FAIL: compile used RETURN(%p) which does not point into expbuf\n",
		       (void *) arg_of_RETURN);
		fail++;
	}
	if (fail)
		totalfail++;
	else
		printf("OK\n");

	printf("TEST: compile regexp with too many numbers in \\{\\}\n");
	fail = 0;
	ptr = compile("z\\{1,2,3\\}", expbuf, expbuf + buflen, '\0');
	if (ptr != &is_ERROR) {
		printf("FAIL: compile did not use ERROR\n");
		fail++;
	} else if (arg_of_ERROR != 44) {
		printf("FAIL: compile used ERROR(%d), not ERROR(44)\n",
		       arg_of_ERROR);
		fail++;
	}
	if (fail)
		totalfail++;
	else
		printf("OK\n");

	return totalfail ? EXIT_FAILURE : EXIT_SUCCESS;
}

-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.26-1-686
Locale: LANG=fi_FI.UTF-8, LC_CTYPE=fi_FI.UTF-8 (charmap=UTF-8)

Versions of packages libc6-dev depends on:
ii  libc6                     2.7-16         GNU C Library: Shared libraries
ii  linux-libc-dev            2.6.26-9.kon.1 Linux support headers for userspac

Versions of packages libc6-dev recommends:
ii  gcc [c-compiler]              4:4.3.1-2  The GNU C compiler
ii  gcc-3.3 [c-compiler]          1:3.3.5-12 The GNU C compiler
ii  gcc-3.4 [c-compiler]          3.4.6-1    The GNU C compiler
ii  gcc-4.0 [c-compiler]          4.0.3-3    The GNU C compiler
ii  gcc-4.1 [c-compiler]          4.1.2-22   The GNU C compiler
ii  gcc-4.2 [c-compiler]          4.2.4-3    The GNU C compiler
ii  gcc-4.3 [c-compiler]          4.3.1-4    The GNU C compiler
ii  tcc [c-compiler]              0.9.24-1   the smallest ANSI C compiler

-- no debconf information

Attachment: pgpfOaKA3Gvxv.pgp
Description: PGP signature


Reply to: