[Top][All Lists]
[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
- [Bug-gnulib] addition: xsize.h,
Bruno Haible <=