svn commit: r265367 - head/lib/libc/regex

Bruce Evans brde at optusnet.com.au
Tue May 6 03:57:06 UTC 2014


On Tue, 6 May 2014, Andrey Chernov wrote:

> On 05.05.2014 22:28, David Chisnall wrote:
>> On 5 May 2014, at 18:42, Andrey Chernov <ache at freebsd.org> wrote:
>>
>>> Please don't commit OpenBSD errors. Now you mix calloc() with the
>>> realloc() for the same variable later which makes calloc() zeroing
>>> pointless and waste of CPU.

The existence of calloc() is a bug.  OpenBSD might be using it to zero
memory, but this zeroing should be explicit.  I didn't really notice
before that the implicit zeroing doesn't even give much shorter code,
since you still need explicit zeroing after realloc() if you have a
policy of zeroing everything.

>> The purpose of calloc() here is not (primarily) to get the zero'd size, it's to get the overflow-checking behaviour for calloc.

It didn't help get the line-length overflow checking in mail.

> It is better to avoid using undocumented intrinsic knowledge of standard
> function particular implementation, this is unportable at least and hard
> to understand too.

It is unportable.  The behaviour on overflow is undefined.  See another reply.

The overflow checking is painful, but doing it in calloc() is only a
minor simplification.  In ps, I needed the following.  It is complicated
enough even for system input ({ARG_MAX}) that can be trusted to some
extent.

% 	if (buf == NULL) {
% 		if ((arg_max = sysconf(_SC_ARG_MAX)) == -1)
% 			errx(1, "sysconf _SC_ARG_MAX failed");
% 		if (arg_max >= LONG_MAX / 4 || arg_max >= (long)(SIZE_MAX / 4))
% 			errx(1, "sysconf _SC_ARG_MAX preposterously large");
% 		buf_size = 4 * arg_max + 1;
% 		if ((buf = malloc(buf_size)) == NULL)
% 			errx(1, "malloc failed");
% 	}

Here we can't simply use calloc(4, sysconf(...)) (or is it
calloc(sysconf(...), 4)?) because:
- sysconf() has type long, which differs from size_t, so we can't even
   pass sysconf() to calloc() in general
- sysconf() has an out of band error value
- we don't quite have an array, and want to add 1.  Adding 1 might overflow.

The above is long partly because it has excessive error handling.  This
much error handling is probably justified for user input but not for
sysconf().  Now I don't even like checking if malloc() failed.  malloc()
never fails, and if it does then there is nothing much you can do.  A
core dump is quite good error handling for it.  But error handling like
this allows giving specific error messages.  If you use calloc() and
the multiplication overflows, then the behaviour can be anything.  If
the behaviour is to return 0 and set errno to indicate the error, then
the best that you can do is hope than errno is set to the undocumented
value EINVAL or EOVERFLOW and then possibly check the multiplication
yourself so as to determine if that was the error, and then print a
specific error message.

Bruce


More information about the svn-src-all mailing list