mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
strtok can return NULL here. We don't need to use strtok anyway, so just use a simple strchr method. Coverity-ID: 1055642 This is CVE-2013-4369 / XSA-68 Signed-off-by: Matthew Daley <mattjd@gmail.com> Fix type. Add test case Signed-off-by: Ian Campbell <Ian.campbell@citrix.com>
149 lines
3.6 KiB
C
149 lines
3.6 KiB
C
#include "libxl_osdeps.h" /* must come before any other headers */
|
|
#include "libxlu_internal.h"
|
|
|
|
static const char *vif_bytes_per_sec_re = "^[0-9]+[GMK]?[Bb]/s$";
|
|
static const char *vif_internal_usec_re = "^[0-9]+[mu]?s?$";
|
|
|
|
static void xlu__vif_err(XLU_Config *cfg, const char *msg, const char *rate) {
|
|
fprintf(cfg->report,
|
|
"%s: config parsing error in vif: %s in `%s'\n",
|
|
cfg->config_source, msg, rate);
|
|
}
|
|
|
|
static int vif_parse_rate_bytes_per_sec(XLU_Config *cfg, const char *bytes,
|
|
uint64_t *bytes_per_sec)
|
|
{
|
|
regex_t rec;
|
|
uint64_t tmp = 0;
|
|
const char *p;
|
|
int rc = 0;
|
|
|
|
regcomp(&rec, vif_bytes_per_sec_re, REG_EXTENDED|REG_NOSUB);
|
|
if (regexec(&rec, bytes, 0, NULL, 0)) {
|
|
xlu__vif_err(cfg, "invalid rate", bytes);
|
|
rc = EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
p = bytes;
|
|
tmp = strtoull(p, (char**)&p, 0);
|
|
if (tmp == 0 || tmp > UINT32_MAX || errno == ERANGE) {
|
|
xlu__vif_err(cfg, "rate overflow", bytes);
|
|
rc = EOVERFLOW;
|
|
goto out;
|
|
}
|
|
|
|
if (*p == 'G')
|
|
tmp *= 1000 * 1000 * 1000;
|
|
else if (*p == 'M')
|
|
tmp *= 1000 * 1000;
|
|
else if (*p == 'K')
|
|
tmp *= 1000;
|
|
if (*p == 'b' || *(p+1) == 'b')
|
|
tmp /= 8;
|
|
|
|
*bytes_per_sec = tmp;
|
|
|
|
out:
|
|
regfree(&rec);
|
|
return rc;
|
|
}
|
|
|
|
static int vif_parse_rate_interval_usecs(XLU_Config *cfg, const char *interval,
|
|
uint32_t *interval_usecs)
|
|
{
|
|
regex_t rec;
|
|
uint64_t tmp = 0;
|
|
const char *p;
|
|
int rc = 0;
|
|
|
|
regcomp(&rec, vif_internal_usec_re, REG_EXTENDED|REG_NOSUB);
|
|
if (regexec(&rec, interval, 0, NULL, 0)) {
|
|
xlu__vif_err(cfg, "invalid replenishment interval", interval);
|
|
rc = EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
p = interval;
|
|
tmp = strtoull(p, (char**)&p, 0);
|
|
if (tmp == 0 || tmp > UINT32_MAX || errno == ERANGE) {
|
|
xlu__vif_err(cfg, "replenishment interval overflow", interval);
|
|
rc = EOVERFLOW;
|
|
goto out;
|
|
}
|
|
|
|
if (*p == 's' || *p == '\0')
|
|
tmp *= 1000 * 1000;
|
|
else if (*p == 'm')
|
|
tmp *= 1000;
|
|
|
|
if (tmp > UINT32_MAX) {
|
|
xlu__vif_err(cfg, "replenishment interval overflow", interval);
|
|
rc = EOVERFLOW;
|
|
goto out;
|
|
}
|
|
|
|
*interval_usecs = (uint32_t) tmp;
|
|
|
|
out:
|
|
regfree(&rec);
|
|
return rc;
|
|
}
|
|
|
|
int xlu_vif_parse_rate(XLU_Config *cfg, const char *rate, libxl_device_nic *nic)
|
|
{
|
|
uint64_t bytes_per_sec = 0;
|
|
uint64_t bytes_per_interval = 0;
|
|
uint32_t interval_usecs = 50000UL; /* Default to 50ms */
|
|
char *p, *tmprate;
|
|
int rc = 0;
|
|
|
|
tmprate = strdup(rate);
|
|
if (tmprate == NULL) {
|
|
rc = ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
p = strchr(tmprate, '@');
|
|
if (p != NULL)
|
|
*p++ = 0;
|
|
|
|
if (!strcmp(tmprate,"")) {
|
|
xlu__vif_err(cfg, "no rate specified", rate);
|
|
rc = EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
rc = vif_parse_rate_bytes_per_sec(cfg, tmprate, &bytes_per_sec);
|
|
if (rc) goto out;
|
|
|
|
if (p != NULL) {
|
|
rc = vif_parse_rate_interval_usecs(cfg, p, &interval_usecs);
|
|
if (rc) goto out;
|
|
}
|
|
|
|
if (interval_usecs != 0 && (bytes_per_sec > (UINT64_MAX / interval_usecs))) {
|
|
xlu__vif_err(cfg, "rate overflow", rate);
|
|
rc = EOVERFLOW;
|
|
goto out;
|
|
}
|
|
|
|
bytes_per_interval =
|
|
(((uint64_t) bytes_per_sec * (uint64_t) interval_usecs) / 1000000UL);
|
|
|
|
nic->rate_interval_usecs = interval_usecs;
|
|
nic->rate_bytes_per_interval = bytes_per_interval;
|
|
|
|
out:
|
|
free(tmprate);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|