[Top][All Lists]

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

[Bug-gnulib] Re: strnstr

From: Simon Josefsson
Subject: [Bug-gnulib] Re: strnstr
Date: Thu, 30 Sep 2004 01:19:06 +0200
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3.50 (gnu/linux)

Paul Eggert <address@hidden> writes:

> Bruno Haible <address@hidden> writes:
>> Simon Josefsson wrote:
>>> Darwin and FreeBSD has this, and GnuTLS is using it.
>> Hmm. FreeBSD has some str'n' functions that work on truncated strings,
>> i.e. it always uses  MIN (strlen(s), N)  as actual length. This seems
>> like a broken concept to me, because
>>   - it is slower than just using strlen(s) or N as actual length,
>>   - it provides the illusion of being safe, but isn't because it will
>>     silently truncate strings, thus producing garbage effects at will,
>>   - the common GNU concept is to allocate strings that are as long as
>>     they need to be.
> I agree pretty much on all these points.

FWIW, I felt the same when I learned about strnstr.

The reason I rewrote strnstr.c, instead of using the GnuTLS version,
was that I wasn't sure the GnuTLS replacement implemented the proper
strnstr.  It look like the hypothetical memstr at first.

Thinking about it now, I realize replacing the GnuTLS code with my
rewrite may be bad.  The name confused me; I assumed that since the
function was called strnstr, it really was the proper strnstr API that
was intended.  Given the implementation, I'm not sure that's the case.

Hm.  It also seems that GnuTLS on platforms that DO have strnstr might
do the wrong thing.  OTOH, since nobody complained, perhaps those
strings that GnuTLS hand to strnstr happen to be zero terminated in
practice, and also doesn't contain more than one embedded zero's.

It is somewhat late, so I'll attach the old GnuTLS strnstr.c below, so
you can read it.  To me (right now) it doesn't look like it is neither
memstr nor strnstr.  It is not memstr, because strncmp is used, which
would stop comparing at the first zero.  And it is not strnstr,
because it skip over embedded zero's in HAYSTACK.

OTOH, it depends on what memstr should be.  Either:

char *memstr (char *haystack, size_t haysize, char *needle);


char *memstr (const char *haystack, size_t haysize,
              const char *needle, size_t needlelen);

?  The code below seem to match the former memstr.

> However, your use in GnuTLS appears to be different. You are using
> functions that work on pieces of buffers, i.e. on not NUL terminated
> memory regions, right? If so, what is the complete list of functions
> that you need? memchr(), memrchr(), memstr(), memrstr(), I guess?

I think the best would be to add the old GnuTLS approach as memstr.
I'm not sure the other functions are needed.

Shouldn't be trying to think at this hour,

char *strnstr(const char *haystack, const char *needle, size_t haystacklen)
        char *p;
        ssize_t plen;
        ssize_t len = strlen(needle);

        if (*needle == '\0')    /* everything matches empty string */
                return (char*) haystack;

        plen = haystacklen;
        for (p = (char*) haystack; p != NULL; p = memchr(p + 1, *needle, 
plen-1)) {
                plen = haystacklen - (p - haystack);

                if (plen < len) return NULL;

                if (strncmp(p, needle, len) == 0)
                        return (p);
        return NULL;

reply via email to

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