source: openpam/trunk/lib/libpam/openpam_readlinev.c @ 877

Last change on this file since 877 was 877, checked in by Dag-Erling Smørgrav, 5 years ago

Plug potential memory leak reported by Coverity Scan. I'm not sure it
can actually ever occur, but the extra free() is harmless, provided we
make sure not to free() something we're still using.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.9 KB
Line 
1/*-
2 * Copyright (c) 2012 Dag-Erling Smørgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 *    products derived from this software without specific prior written
15 *    permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: openpam_readlinev.c 877 2016-01-09 17:26:18Z des $
30 */
31
32#ifdef HAVE_CONFIG_H
33# include "config.h"
34#endif
35
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39
40#include <security/pam_appl.h>
41
42#include "openpam_impl.h"
43
44#define MIN_WORDV_SIZE  32
45
46/*
47 * OpenPAM extension
48 *
49 * Read a line from a file and split it into words.
50 */
51
52char **
53openpam_readlinev(FILE *f, int *lineno, int *lenp)
54{
55        char *word, **wordv, **tmp;
56        size_t wordlen, wordvsize;
57        int ch, serrno, wordvlen;
58
59        wordvsize = MIN_WORDV_SIZE;
60        wordvlen = 0;
61        if ((wordv = malloc(wordvsize * sizeof *wordv)) == NULL) {
62                openpam_log(PAM_LOG_ERROR, "malloc(): %m");
63                errno = ENOMEM;
64                return (NULL);
65        }
66        wordv[wordvlen] = NULL;
67        while ((word = openpam_readword(f, lineno, &wordlen)) != NULL) {
68                if ((unsigned int)wordvlen + 1 >= wordvsize) {
69                        /* need to expand the array */
70                        wordvsize *= 2;
71                        tmp = realloc(wordv, wordvsize * sizeof *wordv);
72                        if (tmp == NULL) {
73                                openpam_log(PAM_LOG_ERROR, "malloc(): %m");
74                                errno = ENOMEM;
75                                break;
76                        }
77                        wordv = tmp;
78                }
79                /* insert our word */
80                wordv[wordvlen++] = word;
81                wordv[wordvlen] = NULL;
82                word = NULL;
83        }
84        if (errno != 0) {
85                /* I/O error or out of memory */
86                serrno = errno;
87                while (wordvlen--)
88                        free(wordv[wordvlen]);
89                free(wordv);
90                free(word);
91                errno = serrno;
92                return (NULL);
93        }
94        /* assert(!ferror(f)) */
95        ch = fgetc(f);
96        /* assert(ch == EOF || ch == '\n') */
97        if (ch == EOF && wordvlen == 0) {
98                free(wordv);
99                return (NULL);
100        }
101        if (ch == '\n' && lineno != NULL)
102                ++*lineno;
103        if (lenp != NULL)
104                *lenp = wordvlen;
105        return (wordv);
106}
107
108/**
109 * The =openpam_readlinev function reads a line from a file, splits it
110 * into words according to the rules described in the =openpam_readword
111 * manual page, and returns a list of those words.
112 *
113 * If =lineno is not =NULL, the integer variable it points to is
114 * incremented every time a newline character is read.
115 * This includes quoted or escaped newline characters and the newline
116 * character at the end of the line.
117 *
118 * If =lenp is not =NULL, the number of words on the line is stored in the
119 * variable to which it points.
120 *
121 * RETURN VALUES
122 *
123 * If successful, the =openpam_readlinev function returns a pointer to a
124 * dynamically allocated array of pointers to individual dynamically
125 * allocated NUL-terminated strings, each containing a single word, in the
126 * order in which they were encountered on the line.
127 * The array is terminated by a =NULL pointer.
128 *
129 * The caller is responsible for freeing both the array and the individual
130 * strings by passing each of them to =!free.
131 *
132 * If the end of the line was reached before any words were read,
133 * =openpam_readlinev returns a pointer to a dynamically allocated array
134 * containing a single =NULL pointer.
135 *
136 * The =openpam_readlinev function can fail and return =NULL for one of
137 * four reasons:
138 *
139 *  - The end of the file was reached before any words were read; :errno is
140 *    zero, =!ferror returns zero, and =!feof returns a non-zero value.
141 *
142 *  - The end of the file was reached while a quote or backslash escape
143 *    was in effect; :errno is set to =EINVAL, =!ferror returns zero, and
144 *    =!feof returns a non-zero value.
145 *
146 *  - An error occurred while reading from the file; :errno is non-zero,
147 *    =!ferror returns a non-zero value and =!feof returns zero.
148 *
149 *  - A =!malloc or =!realloc call failed; :errno is set to =ENOMEM,
150 *    =!ferror returns a non-zero value, and =!feof may or may not return
151 *    a non-zero value.
152 *
153 * >openpam_readline
154 * >openpam_readword
155 *
156 * AUTHOR DES
157 */
Note: See TracBrowser for help on using the repository browser.