source: lib/ini.c @ ba7618d

Last change on this file since ba7618d was ea39049, checked in by dequis <dx@…>, at 2015-12-17T16:56:25Z

ini: Null check file parameter before passing it to open()

The test suite does this. It's harmless in practice but open() is
declared as nonnull. Thanks to clang's ubsan.

  • Property mode set to 100644
File size: 3.1 KB
Line 
1/********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2008 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* INI file reading code                                                */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
24*/
25#define BITLBEE_CORE
26#include "bitlbee.h"
27
28ini_t *ini_open(char *file)
29{
30        int fd = -1;
31        ini_t *ini = NULL;
32        struct stat fi;
33
34        if (file && (fd = open(file, O_RDONLY)) != -1 &&
35            fstat(fd, &fi) == 0 &&
36            fi.st_size <= 16384 &&
37            (ini = g_malloc(sizeof(ini_t) + fi.st_size + 1)) &&
38            read(fd, ini->file, fi.st_size) == fi.st_size) {
39                memset(ini, 0, sizeof(ini_t));
40                ini->size = fi.st_size;
41                ini->file[ini->size] = 0;
42                ini->cur = ini->file;
43                ini->c_section = "";
44
45                close(fd);
46
47                return ini;
48        }
49
50        if (fd >= 0) {
51                close(fd);
52        }
53
54        ini_close(ini);
55
56        return NULL;
57}
58
59/* Strips leading and trailing whitespace and returns a pointer to the first
60   non-ws character of the given string. */
61static char *ini_strip_whitespace(char *in)
62{
63        char *e;
64
65        while (g_ascii_isspace(*in)) {
66                in++;
67        }
68
69        e = in + strlen(in) - 1;
70        while (e > in && g_ascii_isspace(*e)) {
71                e--;
72        }
73        e[1] = 0;
74
75        return in;
76}
77
78int ini_read(ini_t *file)
79{
80        char *s;
81
82        while (file->cur && file->cur < file->file + file->size) {
83                char *e, *next;
84
85                file->line++;
86
87                /* Find the end of line */
88                if ((e = strchr(file->cur, '\n')) != NULL) {
89                        *e = 0;
90                        next = e + 1;
91                } else {
92                        /* No more lines. */
93                        e = file->cur + strlen(file->cur);
94                        next = NULL;
95                }
96
97                /* Comment? */
98                if ((s = strchr(file->cur, '#')) != NULL) {
99                        *s = 0;
100                }
101
102                file->cur = ini_strip_whitespace(file->cur);
103
104                if (*file->cur == '[') {
105                        file->cur++;
106                        if ((s = strchr(file->cur, ']')) != NULL) {
107                                *s = 0;
108                                file->c_section = file->cur;
109                        }
110                } else if ((s = strchr(file->cur, '=')) != NULL) {
111                        *s = 0;
112                        file->key = ini_strip_whitespace(file->cur);
113                        file->value = ini_strip_whitespace(s + 1);
114
115                        if ((s = strchr(file->key, '.')) != NULL) {
116                                *s = 0;
117                                file->section = file->key;
118                                file->key = s + 1;
119                        } else {
120                                file->section = file->c_section;
121                        }
122
123                        file->cur = next;
124                        return 1;
125                }
126                /* else: noise/comment/etc, let's just ignore it. */
127
128                file->cur = next;
129        }
130
131        return 0;
132}
133
134void ini_close(ini_t *file)
135{
136        g_free(file);
137}
Note: See TracBrowser for help on using the repository browser.