summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--popt.c13
-rw-r--r--poptconfig.c142
-rw-r--r--test1.c4
3 files changed, 95 insertions, 64 deletions
diff --git a/popt.c b/popt.c
index acd21b9..6c02a22 100644
--- a/popt.c
+++ b/popt.c
@@ -325,6 +325,9 @@ longOptionStrcmp(const struct poptOption * opt,
const char * optLongName = opt->longName;
int rc;
+ if (optLongName == NULL || longName == NULL) /* XXX can't heppen */
+ return 0;
+
if (F_ISSET(opt, TOGGLE)) {
if (optLongName[0] == 'n' && optLongName[1] == 'o') {
optLongName += sizeof("no") - 1;
@@ -340,9 +343,9 @@ longOptionStrcmp(const struct poptOption * opt,
}
}
}
- rc = (strlen(optLongName) == longNameLen);
+ rc = (int)(strlen(optLongName) == longNameLen);
if (rc)
- rc = !strncmp(optLongName, longName, longNameLen);
+ rc = (int)(strncmp(optLongName, longName, longNameLen) == 0);
return rc;
}
@@ -903,15 +906,15 @@ static unsigned int poptArgInfo(poptContext con, const struct poptOption * opt)
/*@*/
{
unsigned int argInfo = opt->argInfo;
+
+ if (con->os->argv != NULL && con->os->next > 0 && opt->longName != NULL)
if (LF_ISSET(TOGGLE)) {
const char * longName = con->os->argv[con->os->next-1];
while (*longName == '-') longName++;
/* XXX almost good enough but consider --[no]nofoo corner cases. */
if (longName[0] != opt->longName[0] || longName[1] != opt->longName[1])
{
- if (LF_ISSET(XOR)) /* XXX dont toggle with XOR */
- ;
- else {
+ if (!LF_ISSET(XOR)) { /* XXX dont toggle with XOR */
/* Toggle POPT_BIT_SET <=> POPT_BIT_CLR. */
if (LF_ISSET(LOGICALOPS))
argInfo ^= (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND);
diff --git a/poptconfig.c b/poptconfig.c
index c654bc2..2b4c686 100644
--- a/poptconfig.c
+++ b/poptconfig.c
@@ -12,6 +12,13 @@
#if defined(HAVE_FNMATCH_H)
#include <fnmatch.h>
+
+#if defined(__LCLINT__)
+/*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/
+extern int fnmatch (const char *__pattern, const char *__name, int __flags)
+ /*@*/;
+/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
+#endif /* __LCLINT__ */
#endif
#if defined(HAVE_GLOB_H)
@@ -33,7 +40,39 @@ extern void globfree (/*@only@*/ glob_t *__pglob)
extern int glob_pattern_p (const char *__pattern, int __quote)
/*@*/;
/*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
-#endif
+#endif /* __LCLINT__ */
+
+#if !defined(_GNU_SOURCE)
+/* Return nonzero if PATTERN contains any metacharacters.
+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
+static int
+glob_pattern_p (const char * pattern, int quote)
+ /*@*/
+{
+ const char * p;
+ int open = 0;
+
+ for (p = pattern; *p != '\0'; ++p)
+ switch (*p) {
+ case '?':
+ case '*':
+ return 1;
+ /*@notreached@*/ /*@switchbreak@*/ break;
+ case '\\':
+ if (quote && p[1] != '\0')
+ ++p;
+ /*@switchbreak@*/ break;
+ case '[':
+ open = 1;
+ /*@switchbreak@*/ break;
+ case ']':
+ if (open)
+ return 1;
+ /*@switchbreak@*/ break;
+ }
+ return 0;
+}
+#endif /* !defined(_GNU_SOURCE) */
/*@unchecked@*/
static int poptGlobFlags = 0;
@@ -99,38 +138,6 @@ static int poptGlob(/*@unused@*/ UNUSED(poptContext con), const char * pattern,
/*@access poptContext @*/
-#if defined(HAVE_GLOB_H) && !defined(_GNU_SOURCE)
-/* Return nonzero if PATTERN contains any metacharacters.
- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
-static int
-glob_pattern_p (const char * pattern, int quote)
- /*@*/
-{
- const char * p;
- int open = 0;
-
- for (p = pattern; *p != '\0'; ++p)
- switch (*p) {
- case '?':
- case '*':
- return 1;
- /*@notreached@*/ /*@switchbreak@*/ break;
- case '\\':
- if (quote && p[1] != '\0')
- ++p;
- /*@switchbreak@*/ break;
- case '[':
- open = 1;
- /*@switchbreak@*/ break;
- case ']':
- if (open)
- return 1;
- /*@switchbreak@*/ break;
- }
- return 0;
-}
-#endif /* defined(HAVE_GLOB_H) && !defined(_GNU_SOURCE) */
-
/**
* Read a file into a buffer.
* @param con context
@@ -141,7 +148,8 @@ glob_pattern_p (const char * pattern, int quote)
*/
static int poptSlurp(/*@unused@*/ UNUSED(poptContext con), const char * fn,
char ** bp, off_t * nbp)
- /*@modifies *bp, *nbp @*/
+ /*@globals errno, fileSystem, internalState @*/
+ /*@modifies *bp, *nbp, errno, fileSystem, internalState @*/
{
int fdno;
char * b = NULL;
@@ -155,7 +163,7 @@ static int poptSlurp(/*@unused@*/ UNUSED(poptContext con), const char * fn,
if ((nb = lseek(fdno, 0, SEEK_END)) == (off_t)-1
|| lseek(fdno, 0, SEEK_SET) == (off_t)-1
- || (b = malloc((size_t)nb + 1)) == NULL
+ || (b = calloc(sizeof(*b), (size_t)nb + 1)) == NULL
|| read(fdno, (char *)b, (size_t)nb) != (ssize_t)nb)
{
int oerrno = errno;
@@ -165,24 +173,26 @@ static int poptSlurp(/*@unused@*/ UNUSED(poptContext con), const char * fn,
}
if (close(fdno) == -1)
goto exit;
+ if (b == NULL || nb <= 0) {
+ rc = POPT_ERROR_BADCONFIG;
+ goto exit;
+ }
rc = 0;
/* Trim out escaped newlines. */
- s = t = b;
- se = b + nb;
- while (*s && s < se)
+ for (t = b, s = b, se = b + nb; *s && s < se; s++) {
switch (*s) {
case '\\':
if (s[1] == '\n') {
s++;
- s++;
continue;
}
/*@fallthrough@*/
default:
- *t++ = *s++;
- break;
+ *t++ = *s;
+ /*@switchbreak@*/ break;
}
+ }
*t++ = '\0';
nb = (off_t)(t - b);
@@ -191,10 +201,14 @@ exit:
*bp = b;
*nbp = nb;
} else {
+ if (b)
+ free(b);
*bp = NULL;
*nbp = 0;
}
+/*@-compdef -nullstate @*/ /* XXX cannot annotate char ** correctly */
return rc;
+/*@=compdef =nullstate @*/
}
/**
@@ -206,11 +220,16 @@ exit:
static int configAppMatch(poptContext con, const char * s)
/*@*/
{
- int rc;
+ int rc = 1;
+
+ if (con->appName == NULL) /* XXX can't happen. */
+ return rc;
#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
if (glob_pattern_p(s, 1)) {
+/*@-bitwisesigned@*/
static int flags = FNM_EXTMATCH | FNM_PATHNAME | FNM_PERIOD;
+/*@=bitwisesigned@*/
rc = fnmatch(s, con->appName, flags);
} else
#endif
@@ -219,8 +238,9 @@ static int configAppMatch(poptContext con, const char * s)
}
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
-static int configLine(poptContext con, char * line)
- /*@modifies con @*/
+static int poptConfigLine(poptContext con, char * line)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies con, fileSystem, internalState @*/
{
char *b = NULL;
off_t nb = 0;
@@ -231,7 +251,7 @@ static int configLine(poptContext con, char * line)
struct poptItem_s item_buf;
poptItem item = &item_buf;
int i, j;
- int rc = 1;
+ int rc = POPT_ERROR_BADCONFIG;
if (con->appName == NULL)
goto exit;
@@ -270,8 +290,11 @@ static int configLine(poptContext con, char * line)
else {
const char * fn = opt;
- /* XXX handle globs and directories? */
- if ((rc = poptSlurp(con, fn, &b, &nb)) != 0) goto exit;
+ /* XXX handle globs and directories in fn? */
+ if ((rc = poptSlurp(con, fn, &b, &nb)) != 0)
+ goto exit;
+ if (b == NULL || nb <= 0)
+ goto exit;
/* Append remaining text to the interpolated file option text. */
if (*se != '\0') {
@@ -283,15 +306,18 @@ static int configLine(poptContext con, char * line)
se = b;
/* Use the basename of the path as the long option name. */
- if ((item->option.longName = strrchr(fn, '/')) != NULL)
- item->option.longName++;
- else
- item->option.longName = fn;
-
- /* Single character basenames are treated as short options instead. */
- if (item->option.longName[1] == '\0') {
- item->option.shortName = (int) item->option.longName[0];
- item->option.longName = NULL;
+ { const char * longName = strrchr(fn, '/');
+ if (longName != NULL)
+ longName++;
+ else
+ longName = fn;
+ if (longName == NULL) /* XXX can't happen. */
+ goto exit;
+ /* Single character basenames are treated as short options. */
+ if (longName[1] != '\0')
+ item->option.longName = longName;
+ else
+ item->option.shortName = longName[0];
}
}
/*@=temptrans@*/
@@ -351,6 +377,8 @@ int poptReadConfigFile(poptContext con, const char * fn)
if ((rc = poptSlurp(con, fn, &b, &nb)) != 0)
return (errno == ENOENT ? 0 : rc);
+ if (b == NULL || nb <= 0)
+ return POPT_ERROR_BADCONFIG;
if ((t = malloc((size_t)nb + 1)) == NULL)
goto exit;
@@ -364,7 +392,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
te = t;
while (*te && _isspaceptr(te)) te++;
if (*te && *te != '#')
- xx = configLine(con, te);
+ xx = poptConfigLine(con, te);
/*@switchbreak@*/ break;
/*@-usedef@*/ /* XXX *se may be uninitialized */
case '\\':
diff --git a/test1.c b/test1.c
index 3265f4b..3cf6ab4 100644
--- a/test1.c
+++ b/test1.c
@@ -33,9 +33,9 @@ static int aVal = 141421;
/*@unchecked@*/
static int bVal = 141421;
/*@unchecked@*/
-static int aFlag = 0x8ace;
+static unsigned int aFlag = 0x8aceU;
/*@unchecked@*/
-static int bFlag = 0x8ace;
+static unsigned int bFlag = 0x8aceU;
/*@unchecked@*/
static int aInt = 271828;