1    	/* A really basic expanding/appendable string type */
2    	
3    	#include <stdlib.h>
4    	#include <sys/time.h>
5    	#include <sys/stat.h>
6    	#include <time.h>
7    	#include <assert.h>
8    	#include <stdio.h>
9    	#include <limits.h>
10   	#include <string.h>
11   	#include <getopt.h>
12   	#include <errno.h>
13   	#include "cstring.h"
14   	
15   	#define INITIAL_SIZE 1024
16   	#define INCREMENT    1024
17   	#define CHECKER_WORD 0xbcd6712a
18   	
19   	struct cstring_header
20   	{
21   		size_t checker;
22   		size_t allocated;
23   		size_t used;
24   		char the_string[];
25   	};
26   	
27   	cstring_t cstring_alloc(void)
28   	{
29   		struct cstring_header *cstring = malloc(INITIAL_SIZE);
30   	
31   		if (cstring == NULL)
32   			return NULL;
33   	
34   		cstring->checker = CHECKER_WORD;
35   		cstring->allocated = INITIAL_SIZE;
36   		cstring->used = 0;
37   		cstring->the_string[0] = '\0';
38   		return cstring;
39   	}
40   	
(1) Event noescape: "cstring_to_chars(cstring_t)" does not free or save its parameter "cstring".
41   	char *cstring_to_chars(cstring_t cstring)
42   	{
43   		struct cstring_header *h = (struct cstring_header *)cstring;
44   	
45   		if (!h) {
46   			return NULL;
47   		}
48   	
49   		assert(h->checker == CHECKER_WORD);
50   		return strdup(h->the_string);
51   	}
52   	
53   	size_t cstring_len(cstring_t cstring)
54   	{
55   		struct cstring_header *h = (struct cstring_header *)cstring;
56   	
57   		if (!h) {
58   			return 0;
59   		}
60   	
61   		assert(h->checker == CHECKER_WORD);
62   		return h->used;
63   	}
64   	
65   	
66   	cstring_t cstring_append_chars(cstring_t cstring, const char *newstring)
67   	{
68   		struct cstring_header *h = (struct cstring_header *)cstring;
69   		size_t newlen;
70   	
(1) Event path: Condition "!h", taking false branch.
71   		if (!h) {
72   			return NULL;
73   		}
74   	
(2) Event path: Condition "h->checker == 3168170282U", taking true branch.
(3) Event path: Falling through to end of if statement.
75   		assert(h->checker == CHECKER_WORD);
(4) Event path: Condition "!newstring", taking false branch.
76   		if (!newstring) {
77   			return NULL;
78   		}
79   	
80   		newlen = h->used + strlen(newstring)+1 + sizeof(struct cstring_header);
(5) Event path: Condition "newlen > h->allocated", taking true branch.
81   		if (newlen > h->allocated) {
82   			size_t new_allocsize = (newlen + 2048) & 0xFFFFFC00;
(6) Event alloc_fn: Storage is returned from allocation function "realloc".
(7) Event assign: Assigning: "tmp" = "realloc(cstring, new_allocsize)".
Also see events: [assign][assign][noescape][return_alloc]
83   			char *tmp = realloc(cstring, new_allocsize);
(8) Event path: Condition "!tmp", taking false branch.
84   			if (!tmp) {
85   				return cstring;
86   			}
87   	
(9) Event assign: Assigning: "cstring" = "tmp".
Also see events: [alloc_fn][assign][assign][noescape][return_alloc]
88   			cstring = tmp;
(10) Event assign: Assigning: "h" = "(struct cstring_header *)cstring".
Also see events: [alloc_fn][assign][assign][noescape][return_alloc]
89   			h = (struct cstring_header *)cstring;
90   			h->allocated = new_allocsize;
91   		}
(11) Event noescape: Resource "h" is not freed or pointed-to in function "strncat".
Also see events: [alloc_fn][assign][assign][assign][return_alloc]
92   		strncat(h->the_string, newstring, h->allocated - h->used -1);
93   		h->used += strlen(newstring);
(12) Event return_alloc: Returning allocated memory "cstring".
Also see events: [alloc_fn][assign][assign][assign][noescape]
94   		return cstring;
95   	}
96   	
97   	cstring_t cstring_append_cstring(cstring_t cstring, cstring_t newstring)
98   	{
99   		/* Just check the newstring - cstring_append_chars() will check the target */
100  		struct cstring_header *h = (struct cstring_header *)newstring;
101  	
102  		if (!h) {
103  			return NULL;
104  		}
105  	
106  		assert(h->checker == CHECKER_WORD);
107  		return cstring_append_chars(cstring, h->the_string);
108  	}
109  	
110  	cstring_t cstring_from_chars(const char* chars)
111  	{
112  		cstring_t new_string = cstring_alloc();
113  		if (!new_string) {
114  			return NULL;
115  		}
116  		return cstring_append_chars(new_string, chars);
117  	}
118  	
119  	void cstring_free(cstring_t cstring)
120  	{
121  		struct cstring_header *h = (struct cstring_header *)cstring;
122  	
123  		if (!h) {
124  			return;
125  		}
126  		assert(h->checker == CHECKER_WORD);
127  		free(cstring);
128  	}
129  	
130  	
131