bug-gnulib
[Top][All Lists]
Advanced

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

[Bug-gnulib] addition: xsize.h


From: Bruno Haible
Subject: [Bug-gnulib] addition: xsize.h
Date: Tue, 4 Nov 2003 13:15:36 +0100
User-agent: KMail/1.5

Hi,

I've now added this xsize.h as a new module.

It's not that inefficient. Look at the generated code for the xsum4/xtimes
expression:

          size_t m = iconv_string_length (to_utf8, s, n);
          if (m != (size_t)(-1))
            {
              /* Convert the string to UTF-8 and build a translation table
                 from offsets into s to offsets into the translated string.  */
              size_t memory_size =
                xsum4 (xtimes (n, sizeof (size_t)), m, m,
                       (o != NULL ? m : 0));
              char *memory =
                (size_in_bounds_p (memory_size) ? malloc (memory_size) : NULL);

---> (gcc -O2) --->

        call    iconv_string_length
        addl    $16, %esp
        movl    %eax, -44(%ebp)
        incl    %eax
        je      .L870
        cmpl    $1073741824, %esi
        leal    0(,%esi,4), %ebx
        sbbl    %eax, %eax
        xorl    $-1, %eax
        orl     %eax, %ebx
        movl    -44(%ebp), %eax
        testl   %edi, %edi
        sete    %dl
        andl    $255, %edx
        decl    %edx
        andl    %eax, %edx
        movl    -44(%ebp), %eax
        leal    (%eax,%ebx), %ecx
        cmpl    %ebx, %ecx
        movl    -44(%ebp), %ebx
        sbbl    %eax, %eax
        orl     %ecx, %eax
        leal    (%ebx,%eax), %ecx
        cmpl    %eax, %ecx
        sbbl    %eax, %eax
        orl     %ecx, %eax
        leal    (%edx,%eax), %edx
        cmpl    %eax, %edx
        sbbl    %eax, %eax
        orl     %edx, %eax
        cmpl    $-1, %eax
        je      .L885
        subl    $12, %esp
        pushl   %eax
        call    malloc

xsum4 and xtimes give code containing no conditional branch, i.e. it
pipelines well.


2003-11-04  Bruno Haible  <address@hidden>

        * lib/xsize.h: New file.
        * lib/linebreak.c: Include xsize.h.
        (mbs_possible_linebreaks, mbs_width_linebreaks): Check malloc()
        argument for overflow.
        Suggested by Paul Eggert.
        * m4/xsize.m4: New file.
        * modules/xsize: New file.
        * modules/linebreak: Depend on xsize.
        * MODULES.html.sh (func_all_modules): Add xsize.

========================== xsize.h ==========================
/* xsize.h -- Checked size_t computations.

   Copyright (C) 2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifndef _XSIZE_H
#define _XSIZE_H

/* Get size_t.  */
#include <stddef.h>

/* Get SIZE_MAX.  */
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif

/* The size of memory objects is often computed through expressions of
   type size_t. Example:
      void* p = malloc (header_size + n * element_size).
   These computations can lead to overflow.  When this happens, malloc()
   returns a piece of memory that is way too small, and the program then
   crashes while attempting to fill the memory.
   To avoid this, the functions and macros in this file check for overflow.
   The convention is that SIZE_MAX represents overflow.
   malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
   implementation that uses mmap --, it's recommended to use SIZE_OVERFLOW_P
   before invoking malloc().
   The example thus becomes:
      size_t size = xsum (header_size, xtimes (n, element_size));
      void *p = (!SIZE_OVERFLOW_P (size) ? malloc (size) : NULL);
*/

/* Convert an arbitrary value >= 0 to type size_t.  */
#define xcast_size_t(N) \
  ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)

/* Sum of two sizes, with overflow check.  */
static inline size_t
xsum (size_t size1, size_t size2)
{
  size_t sum = size1 + size2;
  return (sum >= size1 ? sum : SIZE_MAX);
}

/* Sum of three sizes, with overflow check.  */
static inline size_t
xsum3 (size_t size1, size_t size2, size_t size3)
{
  return xsum (xsum (size1, size2), size3);
}

/* Sum of four sizes, with overflow check.  */
static inline size_t
xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
{
  return xsum (xsum (xsum (size1, size2), size3), size4);
}

/* Multiplication of a count with an element size, with overflow check.
   The count must be >= 0 and the element size must be > 0.
   This is a macro, not an inline function, so that it works correctly even
   when N is of a wider tupe and N > SIZE_MAX.  */
#define xtimes(N, ELSIZE) \
  ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)

/* Check for overflow.  */
#define size_overflow_p(SIZE) \
  ((SIZE) == SIZE_MAX)
/* Check against overflow.  */
#define size_in_bounds_p(SIZE) \
  ((SIZE) != SIZE_MAX)

#endif /* _XSIZE_H */
========================== xsize.m4 ==========================
# xsize.m4 serial 1
dnl Copyright (C) 2003 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License.  As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.

AC_DEFUN([gl_XSIZE],
[
  dnl Prerequisites of lib/xsize.h.
  AC_CHECK_HEADERS(stdint.h)
])
===============================================================
*** lib/linebreak.c     31 Jul 2003 06:27:05 -0000      1.4
--- lib/linebreak.c     4 Nov 2003 12:05:21 -0000
***************
*** 26,31 ****
--- 26,32 ----
  #include <stdlib.h>
  #include <string.h>
  #include "c-ctype.h"
+ #include "xsize.h"
  
  #include "utf8-ucs4.h"
  
***************
*** 1519,1525 ****
              {
                /* Convert the string to UTF-8 and build a translation table
                   from offsets into s to offsets into the translated string.  
*/
!               char *memory = malloc (n * sizeof (size_t) + m + m);
                if (memory != NULL)
                  {
                    size_t *offtable = (size_t *) memory;
--- 1520,1528 ----
              {
                /* Convert the string to UTF-8 and build a translation table
                   from offsets into s to offsets into the translated string.  
*/
!             size_t memory_size = xsum3 (xtimes (n, sizeof (size_t)), m, m);
!               char *memory =
!               (size_in_bounds_p (memory_size) ? malloc (memory_size) : NULL);
                if (memory != NULL)
                  {
                    size_t *offtable = (size_t *) memory;
***************
*** 1612,1618 ****
              {
                /* Convert the string to UTF-8 and build a translation table
                   from offsets into s to offsets into the translated string.  
*/
!               char *memory = malloc (n * sizeof (size_t) + m + m + (o != NULL 
? m : 0));
                if (memory != NULL)
                  {
                    size_t *offtable = (size_t *) memory;
--- 1615,1625 ----
              {
                /* Convert the string to UTF-8 and build a translation table
                   from offsets into s to offsets into the translated string.  
*/
!             size_t memory_size =
!               xsum4 (xtimes (n, sizeof (size_t)), m, m,
!                      (o != NULL ? m : 0));
!             char *memory =
!               (size_in_bounds_p (memory_size) ? malloc (memory_size) : NULL);
                if (memory != NULL)
                  {
                    size_t *offtable = (size_t *) memory;
*** MODULES.html.sh     20 Oct 2003 11:03:56 -0000      1.45
--- MODULES.html.sh     4 Nov 2003 12:05:21 -0000
***************
*** 1456,1461 ****
--- 1456,1462 ----
    func_echo "$element"
  
    func_begin_table
+   func_module xsize
    func_module xalloc
    func_module alloca
    func_end_table





reply via email to

[Prev in Thread] Current Thread [Next in Thread]