From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8892 invoked by alias); 17 Oct 2006 19:45:22 -0000 Received: (qmail 8876 invoked by uid 22791); 17 Oct 2006 19:45:22 -0000 X-Spam-Check-By: sourceware.org Received: from sunsite.ms.mff.cuni.cz (HELO sunsite.mff.cuni.cz) (195.113.15.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 17 Oct 2006 19:45:17 +0000 Received: from sunsite.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.mff.cuni.cz (8.13.1/8.13.1) with ESMTP id k9HJjD07004428; Tue, 17 Oct 2006 21:45:13 +0200 Received: (from jj@localhost) by sunsite.mff.cuni.cz (8.13.1/8.13.1/Submit) id k9HJjCU7004427; Tue, 17 Oct 2006 21:45:12 +0200 Date: Tue, 17 Oct 2006 19:45:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers Subject: [PATCH] Fix xdr_setpos Message-ID: <20061017194512.GF5868@sunsite.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i Mailing-List: contact libc-hacker-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sourceware.org X-SW-Source: 2006-10/txt/msg00011.txt.bz2 Hi! As shown on the attached testcase (failing on 32-bit arches, as having the middle of address space mmapable in 64-bit VA is very rare), comparing addresses as long ints is a bad idea. The handy != (u_int) handy check might be unnecessary though, as xdrmem_create shouldn't allow creating bigger than 4GB-1 long xdrs. 2006-10-17 Jakub Jelinek * sunrpc/xdr_mem.c (xdrmem_setpos): Don't compare addresses as signed longs, check for x_base + pos overflow. * sunrpc/Makefile (tests): Add tst-xdrmem2. * sunrpc/tst-xdrmem2.c: New test. --- libc/sunrpc/xdr_mem.c.jj 2002-12-16 11:25:27.000000000 +0100 +++ libc/sunrpc/xdr_mem.c 2006-10-17 21:35:25.000000000 +0200 @@ -177,13 +177,15 @@ xdrmem_setpos (xdrs, pos) { caddr_t newaddr = xdrs->x_base + pos; caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + size_t handy = lastaddr - newaddr; - if ((long) newaddr > (long) lastaddr - || (UINT_MAX < LONG_MAX - && (long) UINT_MAX < (long) lastaddr - (long) newaddr)) + if (newaddr > lastaddr + || newaddr < xdrs->x_base + || handy != (u_int) handy) return FALSE; + xdrs->x_private = newaddr; - xdrs->x_handy = (long) lastaddr - (long) newaddr; + xdrs->x_handy = (u_int) handy; return TRUE; } --- libc/sunrpc/Makefile.jj 2005-08-23 12:00:52.000000000 +0200 +++ libc/sunrpc/Makefile 2006-10-17 21:15:48.000000000 +0200 @@ -1,4 +1,4 @@ -# Copyright (C) 1994-2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 1994-2004, 2005, 2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -85,7 +85,7 @@ all: # Make this the default target; it include ../Makeconfig -tests = tst-xdrmem +tests = tst-xdrmem tst-xdrmem2 xtests := tst-getmyaddr ifeq ($(have-thread-library),yes) --- libc/sunrpc/tst-xdrmem2.c.jj 2006-10-17 20:59:59.000000000 +0200 +++ libc/sunrpc/tst-xdrmem2.c 2006-10-17 21:13:32.000000000 +0200 @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + XDR xdrs; + void *buf; + size_t ps = sysconf (_SC_PAGESIZE); + uintptr_t half = -1; + int v_int; + u_short v_u_short; + + half = (half >> 1) & ~(uintptr_t) (ps - 1); + buf = mmap ((void *) half, 2 * ps, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (buf == MAP_FAILED || buf != (void *) half) + { + puts ("Couldn't mmap 2 pages in the middle of address space"); + return 0; + } + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_ENCODE); + +#define T(type, val) \ + v_##type = val; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("encoding of " #type \ + " " #val " failed"); \ + return 1; \ + } + + T(int, 127) + + u_int pos = xdr_getpos (&xdrs); + + T(u_short, 31) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_DECODE); + +#define T(type, val) \ + v_##type = 0x15; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (v_##type != val) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } + + T(int, 127) + + pos = xdr_getpos (&xdrs); + + T(u_short, 36) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" Jakub