selinux/checkpolicy/queue.c
Nicolas Iooss 47f61b0ee9 checkpolicy: do not leak queue elements in queue_destroy()
Elements which are inserted into a queue_t object are either NULL (from
insert_separator()) or strings allocated with malloc() in insert_id().
They would be freed if there are still present in the queue when it is
destroyed. Otherwise the memory allocated for these elements would be
leaked.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
2017-01-06 13:33:15 -05:00

182 lines
2.5 KiB
C

/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
/* FLASK */
/*
* Implementation of the double-ended queue type.
*/
#include <stdlib.h>
#include "queue.h"
queue_t queue_create(void)
{
queue_t q;
q = (queue_t) malloc(sizeof(struct queue_info));
if (q == NULL)
return NULL;
q->head = q->tail = NULL;
return q;
}
int queue_insert(queue_t q, queue_element_t e)
{
queue_node_ptr_t newnode;
if (!q)
return -1;
newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node));
if (newnode == NULL)
return -1;
newnode->element = e;
newnode->next = NULL;
if (q->head == NULL) {
q->head = q->tail = newnode;
} else {
q->tail->next = newnode;
q->tail = newnode;
}
return 0;
}
int queue_push(queue_t q, queue_element_t e)
{
queue_node_ptr_t newnode;
if (!q)
return -1;
newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node));
if (newnode == NULL)
return -1;
newnode->element = e;
newnode->next = NULL;
if (q->head == NULL) {
q->head = q->tail = newnode;
} else {
newnode->next = q->head;
q->head = newnode;
}
return 0;
}
queue_element_t queue_remove(queue_t q)
{
queue_node_ptr_t node;
queue_element_t e;
if (!q)
return NULL;
if (q->head == NULL)
return NULL;
node = q->head;
q->head = q->head->next;
if (q->head == NULL)
q->tail = NULL;
e = node->element;
free(node);
return e;
}
queue_element_t queue_head(queue_t q)
{
if (!q)
return NULL;
if (q->head == NULL)
return NULL;
return q->head->element;
}
void queue_destroy(queue_t q)
{
queue_node_ptr_t p, temp;
if (!q)
return;
p = q->head;
while (p != NULL) {
free(p->element);
temp = p;
p = p->next;
free(temp);
}
free(q);
}
int queue_map(queue_t q, int (*f) (queue_element_t, void *), void *vp)
{
queue_node_ptr_t p;
int ret;
if (!q)
return 0;
p = q->head;
while (p != NULL) {
ret = f(p->element, vp);
if (ret)
return ret;
p = p->next;
}
return 0;
}
void queue_map_remove_on_error(queue_t q,
int (*f) (queue_element_t, void *),
void (*g) (queue_element_t, void *), void *vp)
{
queue_node_ptr_t p, last, temp;
int ret;
if (!q)
return;
last = NULL;
p = q->head;
while (p != NULL) {
ret = f(p->element, vp);
if (ret) {
if (last) {
last->next = p->next;
if (last->next == NULL)
q->tail = last;
} else {
q->head = p->next;
if (q->head == NULL)
q->tail = NULL;
}
temp = p;
p = p->next;
g(temp->element, vp);
free(temp);
} else {
last = p;
p = p->next;
}
}
return;
}
/* FLASK */