[Snort-devel] [SNORT-DEVEL] macro for strcmp() replacement plus strlen() optimization.

Bill Parker wp02855 at ...2499...
Wed Apr 2 13:12:28 EDT 2014


This macro (from Sam's C Unleashed) could be potentially
useful in instances where strcmp() is used in DAQ 2.x.x
and Snort-2.9.6.x/2.9.7.x where a test is made on the
first character of the strings (obviously, if there
is NOT a match, there is no need to check the rest of
the string in question), which may result in a speedup
of approximately 15 to 1, based on letter distribution.

#include <stdio.h>
#include <string.h>

#define SnortStrcmp(a,b)    (*(a) != *(b) ? \
                            (int) ((unsigned char) *(a) - \
                            (unsigned char) *(b)) : \
                            strcmp((a), (b)))

#define DaqStrcmp(a,b) (*(a) != *(b) ? \
                            (int) ((unsigned char) *(a) - \
                            (unsigned char) *(b)) : \
                            strcmp((a), (b)))
int main(void)
{
    char *str1 = "this is a test";
    char *str2 = "not this is a test";
    int val;

    val = SnortStrcmp(str1, str2);

    if (!val)
        printf("strings are equal\n");
    else
        printf("strings are NOT equal...\n");

    return 0;
}

bill at ...3493...:~> ./a.out
strings are NOT equal...

Would this be of any use in optimization improvements
in DAQ-2.0.x or Snort-2.9.6.x or 2.9.7.0-alpha (or
future products) where strcmp() is called?

Also, I noticed calls to strcasecmp() which compares
strings w/out regard to case (i.e. - 'i' is equal to 'I'),
so perhaps the macro for SnortStrcmp could be modified
to make a SnortStrCaseCmp or DaqStrCaseCmp macro?

Additionally, I did notice places where strlen() is
called as either the initial value, or the test value
in a for loop, should these not be re-written so that
the strlen call is made prior to loop entry?

for example in snort-2.9.7.0-alpha/src/parser.c:

    for (i = 0; i < strlen(args); i++)
    {
        /* If we get something other than a digit, assume it's
         * a user name */
        if (!isdigit((int)args[i]))
        {
            struct passwd *pw = getpwnam(args);

            if (pw == NULL)
                ParseError("User \"%s\" unknown.", args);

            sc->user_id = (int)pw->pw_uid;

            /* Why would someone want to run as another user
             * but still as root group? */
            if (sc->group_id == -1)
                sc->group_id = (int)pw->pw_gid;

            break;
        }
    }

would it not be more prudent to initialize another size_t
variable 'x' and do this:

x = strlen(args);

for (i = 0; i < x; i++)

that way, strlen() is only called once?
Bill Parker (wp02855 at gmail dot com)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.snort.org/pipermail/snort-devel/attachments/20140402/821b2f1a/attachment.html>


More information about the Snort-devel mailing list