static void test_ctype(void) { int c; for (c = -1; c < 256; c++) { /* Test blank. */ if (c == '\t' || c == ' ') test_pass(c_isblank(c)); else test_fail(c_isblank(c)); /* Test white. */ if (c == '\t' || c == ' ' || c == '\n') test_pass(c_iswhite(c)); else test_fail(c_iswhite(c)); /* Test space. */ if (c == '\t' || c == '\v' || c == '\f' || c == '\r' || c == '\n' || c == ' ') test_pass(c_isspace(c)); else test_fail(c_isspace(c)); /* Test digit. */ if (c >= '0' && c <= '9') test_pass(c_isdigit(c)); else test_fail(c_isdigit(c)); /* Test lower case. */ if (c >= 'a' && c <= 'z') test_pass(c_islower(c)); else test_fail(c_islower(c)); /* Test upper case. */ if (c >= 'A' && c <= 'Z') test_pass(c_isupper(c)); else test_fail(c_isupper(c)); /* Test alpha. */ if (c_islower(c) || c_isupper(c)) test_pass(c_isalpha(c)); else test_fail(c_isalpha(c)); /* Test alphanumeric. */ if (c_isdigit(c) || c_isalpha(c)) test_pass(c_isalnum(c)); else test_fail(c_isalnum(c)); } }
/** * Parse a version string and check for invalid syntax. * * Distinguish between lax (warnings) and strict (error) parsing. * * @param rversion The parsed version. * @param string The version string to parse. * @param err The warning or error message if any. * * @retval 0 On success. * @retval -1 On failure, and err is set accordingly. */ int parseversion(struct dpkg_version *rversion, const char *string, struct dpkg_error *err) { char *hyphen, *colon, *eepochcolon; const char *end, *ptr; /* Trim leading and trailing space. */ while (*string && c_isblank(*string)) string++; if (!*string) return dpkg_put_error(err, _("version string is empty")); /* String now points to the first non-whitespace char. */ end = string; /* Find either the end of the string, or a whitespace char. */ while (*end && !c_isblank(*end)) end++; /* Check for extra chars after trailing space. */ ptr = end; while (*ptr && c_isblank(*ptr)) ptr++; if (*ptr) return dpkg_put_error(err, _("version string has embedded spaces")); colon= strchr(string,':'); if (colon) { long epoch; errno = 0; epoch = strtol(string, &eepochcolon, 10); if (string == eepochcolon) return dpkg_put_error(err, _("epoch in version is empty")); if (colon != eepochcolon) return dpkg_put_error(err, _("epoch in version is not number")); if (epoch < 0) return dpkg_put_error(err, _("epoch in version is negative")); if (epoch > INT_MAX || errno == ERANGE) return dpkg_put_error(err, _("epoch in version is too big")); if (!*++colon) return dpkg_put_error(err, _("nothing after colon in version number")); string= colon; rversion->epoch= epoch; } else { rversion->epoch= 0; } rversion->version= nfstrnsave(string,end-string); hyphen= strrchr(rversion->version,'-'); if (hyphen) { *hyphen++ = '\0'; if (*hyphen == '\0') return dpkg_put_error(err, _("revision number is empty")); } rversion->revision= hyphen ? hyphen : ""; /* XXX: Would be faster to use something like cisversion and cisrevision. */ ptr = rversion->version; if (!*ptr) return dpkg_put_error(err, _("version number is empty")); if (*ptr && !c_isdigit(*ptr++)) return dpkg_put_warn(err, _("version number does not start with digit")); for (; *ptr; ptr++) { if (!c_isdigit(*ptr) && !c_isalpha(*ptr) && strchr(".-+~:", *ptr) == NULL) return dpkg_put_warn(err, _("invalid character in version number")); } for (ptr = rversion->revision; *ptr; ptr++) { if (!c_isdigit(*ptr) && !c_isalpha(*ptr) && strchr(".+~", *ptr) == NULL) return dpkg_put_warn(err, _("invalid character in revision number")); } return 0; }
static void test_all (void) { int c; for (c = -0x80; c < 0x100; c++) { ASSERT (c_isascii (c) == (c >= 0 && c < 0x80)); switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ASSERT (c_isalnum (c) == 1); break; default: ASSERT (c_isalnum (c) == 0); break; } switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': ASSERT (c_isalpha (c) == 1); break; default: ASSERT (c_isalpha (c) == 0); break; } switch (c) { case '\t': case ' ': ASSERT (c_isblank (c) == 1); break; default: ASSERT (c_isblank (c) == 0); break; } ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f)); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ASSERT (c_isdigit (c) == 1); break; default: ASSERT (c_isdigit (c) == 0); break; } switch (c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': ASSERT (c_islower (c) == 1); break; default: ASSERT (c_islower (c) == 0); break; } ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' ')); ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f)); ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c))); switch (c) { case ' ': case '\t': case '\n': case '\v': case '\f': case '\r': ASSERT (c_isspace (c) == 1); break; default: ASSERT (c_isspace (c) == 0); break; } switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': ASSERT (c_isupper (c) == 1); break; default: ASSERT (c_isupper (c) == 0); break; } switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ASSERT (c_isxdigit (c) == 1); break; default: ASSERT (c_isxdigit (c) == 0); break; } switch (c) { case 'A': ASSERT (c_tolower (c) == 'a'); ASSERT (c_toupper (c) == c); break; case 'B': ASSERT (c_tolower (c) == 'b'); ASSERT (c_toupper (c) == c); break; case 'C': ASSERT (c_tolower (c) == 'c'); ASSERT (c_toupper (c) == c); break; case 'D': ASSERT (c_tolower (c) == 'd'); ASSERT (c_toupper (c) == c); break; case 'E': ASSERT (c_tolower (c) == 'e'); ASSERT (c_toupper (c) == c); break; case 'F': ASSERT (c_tolower (c) == 'f'); ASSERT (c_toupper (c) == c); break; case 'G': ASSERT (c_tolower (c) == 'g'); ASSERT (c_toupper (c) == c); break; case 'H': ASSERT (c_tolower (c) == 'h'); ASSERT (c_toupper (c) == c); break; case 'I': ASSERT (c_tolower (c) == 'i'); ASSERT (c_toupper (c) == c); break; case 'J': ASSERT (c_tolower (c) == 'j'); ASSERT (c_toupper (c) == c); break; case 'K': ASSERT (c_tolower (c) == 'k'); ASSERT (c_toupper (c) == c); break; case 'L': ASSERT (c_tolower (c) == 'l'); ASSERT (c_toupper (c) == c); break; case 'M': ASSERT (c_tolower (c) == 'm'); ASSERT (c_toupper (c) == c); break; case 'N': ASSERT (c_tolower (c) == 'n'); ASSERT (c_toupper (c) == c); break; case 'O': ASSERT (c_tolower (c) == 'o'); ASSERT (c_toupper (c) == c); break; case 'P': ASSERT (c_tolower (c) == 'p'); ASSERT (c_toupper (c) == c); break; case 'Q': ASSERT (c_tolower (c) == 'q'); ASSERT (c_toupper (c) == c); break; case 'R': ASSERT (c_tolower (c) == 'r'); ASSERT (c_toupper (c) == c); break; case 'S': ASSERT (c_tolower (c) == 's'); ASSERT (c_toupper (c) == c); break; case 'T': ASSERT (c_tolower (c) == 't'); ASSERT (c_toupper (c) == c); break; case 'U': ASSERT (c_tolower (c) == 'u'); ASSERT (c_toupper (c) == c); break; case 'V': ASSERT (c_tolower (c) == 'v'); ASSERT (c_toupper (c) == c); break; case 'W': ASSERT (c_tolower (c) == 'w'); ASSERT (c_toupper (c) == c); break; case 'X': ASSERT (c_tolower (c) == 'x'); ASSERT (c_toupper (c) == c); break; case 'Y': ASSERT (c_tolower (c) == 'y'); ASSERT (c_toupper (c) == c); break; case 'Z': ASSERT (c_tolower (c) == 'z'); ASSERT (c_toupper (c) == c); break; case 'a': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'A'); break; case 'b': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'B'); break; case 'c': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'C'); break; case 'd': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'D'); break; case 'e': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'E'); break; case 'f': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'F'); break; case 'g': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'G'); break; case 'h': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'H'); break; case 'i': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'I'); break; case 'j': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'J'); break; case 'k': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'K'); break; case 'l': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'L'); break; case 'm': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'M'); break; case 'n': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'N'); break; case 'o': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'O'); break; case 'p': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'P'); break; case 'q': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'Q'); break; case 'r': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'R'); break; case 's': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'S'); break; case 't': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'T'); break; case 'u': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'U'); break; case 'v': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'V'); break; case 'w': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'W'); break; case 'x': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'X'); break; case 'y': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'Y'); break; case 'z': ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == 'Z'); break; default: ASSERT (c_tolower (c) == c); ASSERT (c_toupper (c) == c); break; } } }
/** * virConfParseString: * @ctxt: the parsing context * * Parse one string * * Returns a pointer to the string or NULL in case of error */ static char * virConfParseString(virConfParserCtxtPtr ctxt) { const char *base; char *ret = NULL; if (CUR == '\'') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '\'') && (!IS_EOL(CUR))) NEXT; if (CUR != '\'') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } else if ((ctxt->cur + 6 < ctxt->end) && (STRPREFIX(ctxt->cur, "\"\"\""))) { /* String starts with python-style triple quotes """ */ ctxt->cur += 3; base = ctxt->cur; /* Find the ending triple quotes */ while ((ctxt->cur + 2 < ctxt->end) && !(STRPREFIX(ctxt->cur, "\"\"\""))) { if (CUR == '\n') ctxt->line++; NEXT; } if (!STRPREFIX(ctxt->cur, "\"\"\"")) { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; ctxt->cur += 3; } else if (CUR == '"') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '"') && (!IS_EOL(CUR))) NEXT; if (CUR != '"') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } else if (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) { base = ctxt->cur; /* LXC config format doesn't support comments after the value */ while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR))) NEXT; /* Reverse to exclude the trailing blanks from the value */ while ((ctxt->cur > base) && (c_isblank(CUR))) ctxt->cur--; if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; } return ret; }