on
OMG WTF OpenSSL
If you are a developer, I highly recommend you follow OpenSSL Valhalla Rampage. The latest entry refers to a file called pqueue.c
. I took a look at the file … boy, that hurts. Let’s pick some highlights.
typedef struct _pqueue {
pitem *items;
int count;
} pqueue_s;
So we have a opaque struct that holds all data of a queue. Note the count element. It is never used. There is a function pqueue_size
but that function walks through the linked list to count the elements:
int
pqueue_size(pqueue_s *pq)
{
pitem *item = pq->items;
int count = 0;
while (item != NULL) {
count++;
item = item->next;
}
return count;
}
To get a new item, there is a function pitem_new
that takes two arguments: The data to store and a pointer to an unsigned char array. As it is obvious from the argument’s name prio64be
this needs to be an array of 8 bytes that represent the priority of the item, stored as big endian.
pitem *
pitem_new(unsigned char *prio64be, void *data)
Why big endian, one might ask. Well, it turns out that pqueue_insert
uses memcmp
to sort the items by priority:
/* we can compare 64-bit value in big-endian encoding
* with memcmp:-) */
int cmp = memcmp(next->priority, item->priority,
sizeof(item->priority));
if (cmp > 0) /* next > item */
{
Of course, you could use uint64_t
for the priority and simply compare that values …
Let’s pick another function:
pqueue_s *
pqueue_new(void)
{
pqueue_s *pq = (pqueue_s *)malloc(sizeof(pqueue_s));
if (pq == NULL)
return NULL;
memset(pq, 0x00, sizeof(pqueue_s));
return pq;
}
Could you simplify this method? How about:
pqueue_s *
pqueue_new(void)
{
return (pqueue_s *)calloc(1, sizeof(pqueue_s));
}
Free could be a bit easier, too. Replace:
void
pqueue_free(pqueue_s *pq)
{
if (pq == NULL)
return;
free(pq);
}
… with …
void
pqueue_free(pqueue_s *pq)
{
free(pq);
}
In pqueue_find
you find:
pitem *found = NULL;
[…]
if (!found)
return NULL;
return found;
And so on. With one or maybe two exception, every single function in the file has (serious) flaws. Besides the copyright, there are 3 lines of documentation (two of them shown above). The third one is:
if (item == NULL || *item == NULL)
return NULL;
/* *item != NULL */
ret = *item;
I truly hope that the LibreSSL guys have enough patience to fix all the mess OpenSSL is.