Eliminate implicit conversions

Use explicit conversions everywhere. Adding bounds check assertions when
necessary.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-03-30 09:07:21 +00:00
parent 532a90d573
commit 0037b7e5fb
35 changed files with 786 additions and 671 deletions

220
src/c2.c
View File

@@ -106,8 +106,8 @@ struct _c2_l {
xcb_atom_t tgtatom;
bool tgt_onframe;
int index;
enum { C2_L_PUNDEFINED,
C2_L_PID,
enum { C2_L_PUNDEFINED = -1,
C2_L_PID = 0,
C2_L_PX,
C2_L_PY,
C2_L_PX2,
@@ -554,17 +554,19 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
}
// Copy target name out
unsigned tgtlen = 0;
int tgtlen = 0;
for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]);
++offset) {
++tgtlen;
}
if (!tgtlen)
if (!tgtlen) {
c2_error("Empty target.");
pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen);
}
pleaf->tgt = strndup(&pattern[offset - tgtlen], (size_t)tgtlen);
// Check for predefined targets
for (unsigned i = 1; i < sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]); ++i) {
static const int npredefs = (int)(sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]));
for (int i = 0; i < npredefs; ++i) {
if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) {
pleaf->predef = i;
pleaf->type = C2_PREDEFS[i].type;
@@ -573,25 +575,6 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
}
}
// Alias for predefined targets
if (!pleaf->predef) {
#define TGTFILL(pdefid) \
(pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \
pleaf->format = C2_PREDEFS[pdefid].format)
// if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt))
// TGTFILL(C2_L_PNAME);
#undef TGTFILL
// Alias for custom properties
#define TGTFILL(target, type, format) \
(pleaf->target = strdup(target), pleaf->type = type, pleaf->format = format)
// if (!strcmp("SOME_ALIAS"))
// TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32);
#undef TGTFILL
}
C2H_SKIP_SPACES();
// Parse target-on-frame flag
@@ -607,27 +590,29 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
C2H_SKIP_SPACES();
int index = -1;
long index = -1;
char *endptr = NULL;
index = strtol(pattern + offset, &endptr, 0);
if (!endptr || pattern + offset == endptr)
if (!endptr || pattern + offset == endptr) {
c2_error("No index number found after bracket.");
if (index < 0)
}
if (index < 0) {
c2_error("Index number invalid.");
if (pleaf->predef)
}
if (pleaf->predef != C2_L_PUNDEFINED) {
c2_error("Predefined targets can't have index.");
}
pleaf->index = index;
offset = endptr - pattern;
pleaf->index = to_int_checked(index);
offset = to_int_checked(endptr - pattern);
C2H_SKIP_SPACES();
if (']' != pattern[offset])
if (pattern[offset] != ']') {
c2_error("Index end marker not found.");
}
++offset;
@@ -641,44 +626,43 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
// Look for format
bool hasformat = false;
int format = 0;
long format = 0;
{
char *endptr = NULL;
format = strtol(pattern + offset, &endptr, 0);
assert(endptr);
if ((hasformat = (endptr && endptr != pattern + offset)))
offset = endptr - pattern;
if ((hasformat = (endptr && endptr != pattern + offset))) {
offset = to_int_checked(endptr - pattern);
}
C2H_SKIP_SPACES();
}
// Look for type
enum c2_l_type type = C2_L_TUNDEFINED;
{
switch (pattern[offset]) {
case 'w': type = C2_L_TWINDOW; break;
case 'd': type = C2_L_TDRAWABLE; break;
case 'c': type = C2_L_TCARDINAL; break;
case 's': type = C2_L_TSTRING; break;
case 'a': type = C2_L_TATOM; break;
default: c2_error("Invalid type character.");
}
if (type) {
if (pleaf->predef) {
log_warn("Type specified for a default target "
"will be ignored.");
} else {
if (pleaf->type && type != pleaf->type)
log_warn("Default type overridden on "
"target.");
pleaf->type = type;
}
}
offset++;
C2H_SKIP_SPACES();
switch (pattern[offset]) {
case 'w': type = C2_L_TWINDOW; break;
case 'd': type = C2_L_TDRAWABLE; break;
case 'c': type = C2_L_TCARDINAL; break;
case 's': type = C2_L_TSTRING; break;
case 'a': type = C2_L_TATOM; break;
default: c2_error("Invalid type character.");
}
if (type) {
if (pleaf->predef != C2_L_PUNDEFINED) {
log_warn("Type specified for a default target "
"will be ignored.");
} else {
if (pleaf->type && type != pleaf->type)
log_warn("Default type overridden on "
"target.");
pleaf->type = type;
}
}
offset++;
C2H_SKIP_SPACES();
// Default format
if (!pleaf->format) {
switch (pleaf->type) {
@@ -692,20 +676,20 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
// Write format
if (hasformat) {
if (pleaf->predef)
log_warn("Format \"%d\" specified on a default target "
if (pleaf->predef != C2_L_PUNDEFINED) {
log_warn("Format \"%ld\" specified on a default target "
"will be ignored.",
format);
else if (C2_L_TSTRING == pleaf->type)
log_warn("Format \"%d\" specified on a string target "
} else if (pleaf->type == C2_L_TSTRING) {
log_warn("Format \"%ld\" specified on a string target "
"will be ignored.",
format);
else {
} else {
if (pleaf->format && pleaf->format != format)
log_warn("Default format %d overridden on "
"target.",
pleaf->format);
pleaf->format = format;
pleaf->format = to_int_checked(format);
}
}
}
@@ -798,52 +782,51 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
c2_l_t *const pleaf = presult->l;
// Exists operator cannot have pattern
if (!pleaf->op)
if (!pleaf->op) {
return offset;
}
C2H_SKIP_SPACES();
char *endptr = NULL;
// Check for boolean patterns
if (!strcmp_wd("true", &pattern[offset])) {
pleaf->ptntype = C2_L_PTINT;
pleaf->ptnint = true;
offset += strlen("true");
offset += 4; // length of "true";
} else if (!strcmp_wd("false", &pattern[offset])) {
pleaf->ptntype = C2_L_PTINT;
pleaf->ptnint = false;
offset += strlen("false");
}
// Check for integer patterns
else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
pattern + offset != endptr) {
offset += 5; // length of "false";
} else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
pattern + offset != endptr) {
pleaf->ptntype = C2_L_PTINT;
offset = endptr - pattern;
offset = to_int_checked(endptr - pattern);
// Make sure we are stopping at the end of a word
if (isalnum(pattern[offset]))
if (isalnum(pattern[offset])) {
c2_error("Trailing characters after a numeric pattern.");
}
// Check for string patterns
else {
}
} else {
// Parse string patterns
bool raw = false;
char delim = '\0';
// String flags
if ('r' == tolower(pattern[offset])) {
if (tolower(pattern[offset]) == 'r') {
raw = true;
++offset;
C2H_SKIP_SPACES();
}
// Check for delimiters
if ('\"' == pattern[offset] || '\'' == pattern[offset]) {
if (pattern[offset] == '\"' || pattern[offset] == '\'') {
pleaf->ptntype = C2_L_PTSTRING;
delim = pattern[offset];
++offset;
}
if (C2_L_PTSTRING != pleaf->ptntype)
if (pleaf->ptntype != C2_L_PTSTRING) {
c2_error("Invalid pattern type.");
}
// Parse the string now
// We can't determine the length of the pattern, so we use the length
@@ -876,8 +859,7 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
if (pstr != &tstr[2] || val <= 0)
c2_error("Invalid octal/hex escape "
"sequence.");
assert(val < 256 && val >= 0);
*(ptptnstr++) = val;
*(ptptnstr++) = to_char_checked(val);
offset += 2;
break;
}
@@ -929,10 +911,10 @@ fail:
* Parse a condition with legacy syntax.
*/
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
unsigned plen = strlen(pattern + offset);
if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':'))
if (strlen(pattern + offset) < 4 || pattern[offset + 1] != ':' ||
!strchr(pattern + offset + 2, ':')) {
c2_error("Legacy parser: Invalid format.");
}
// Allocate memory for new leaf
auto pleaf = cmalloc(c2_l_t);
@@ -1000,7 +982,7 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
}
// Get target atom if it's not a predefined one
if (!pleaf->predef) {
if (pleaf->predef == C2_L_PUNDEFINED) {
pleaf->tgtatom = get_atom(ps, pleaf->tgt);
if (!pleaf->tgtatom) {
log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
@@ -1027,20 +1009,18 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
// Enable specific tracking options in compton if needed by the condition
// TODO: Add track_leader
if (pleaf->predef) {
switch (pleaf->predef) {
case C2_L_PFOCUSED: ps->o.track_focus = true; break;
// case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break;
case C2_L_PNAME:
case C2_L_PCLASSG:
case C2_L_PCLASSI:
case C2_L_PROLE: ps->o.track_wdata = true; break;
default: break;
}
switch (pleaf->predef) {
case C2_L_PFOCUSED: ps->o.track_focus = true; break;
// case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break;
case C2_L_PNAME:
case C2_L_PCLASSG:
case C2_L_PCLASSI:
case C2_L_PROLE: ps->o.track_wdata = true; break;
default: break;
}
// Warn about lower case characters in target name
if (!pleaf->predef) {
if (pleaf->predef == C2_L_PUNDEFINED) {
for (const char *pc = pleaf->tgt; *pc; ++pc) {
if (islower(*pc)) {
log_warn("Lowercase character in target name \"%s\".",
@@ -1160,10 +1140,11 @@ c2_lptr_t *c2_free_lptr(c2_lptr_t *lp) {
* Get a string representation of a rule target.
*/
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
if (pleaf->predef)
if (pleaf->predef != C2_L_PUNDEFINED) {
return C2_PREDEFS[pleaf->predef].name;
else
} else {
return pleaf->tgt;
}
}
/**
@@ -1298,8 +1279,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
// Return if wid is missing
if (!pleaf->predef && !wid)
if (pleaf->predef == C2_L_PUNDEFINED && !wid) {
return;
}
const int idx = (pleaf->index < 0 ? 0 : pleaf->index);
@@ -1310,7 +1292,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
// Get the value
// A predefined target
if (pleaf->predef) {
if (pleaf->predef != C2_L_PUNDEFINED) {
*perr = false;
switch (pleaf->predef) {
case C2_L_PID: tgt = wid; break;
@@ -1355,7 +1337,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
// Do comparison
switch (pleaf->op) {
case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt : true); break;
case C2_L_OEXISTS:
*pres = (pleaf->predef != C2_L_PUNDEFINED ? tgt : true);
break;
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
@@ -1373,7 +1357,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
char *tgt_free = NULL;
// A predefined target
if (pleaf->predef) {
if (pleaf->predef != C2_L_PUNDEFINED) {
switch (pleaf->predef) {
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break;
case C2_L_PNAME: tgt = w->name; break;
@@ -1382,20 +1366,19 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
case C2_L_PROLE: tgt = w->role; break;
default: assert(0); break;
}
}
// If it's an atom type property, convert atom to string
else if (C2_L_TATOM == pleaf->type) {
} else if (pleaf->type == C2_L_TATOM) {
// An atom type property, convert it to string
winprop_t prop =
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
c2_get_atom_type(pleaf), pleaf->format);
xcb_atom_t atom = winprop_get_int(prop);
xcb_atom_t atom = (xcb_atom_t)winprop_get_int(prop);
if (atom) {
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
ps->c, xcb_get_atom_name(ps->c, atom), NULL);
if (reply) {
tgt_free =
strndup(xcb_get_atom_name_name(reply),
xcb_get_atom_name_name_length(reply));
tgt_free = strndup(
xcb_get_atom_name_name(reply),
(size_t)xcb_get_atom_name_name_length(reply));
free(reply);
}
}
@@ -1403,9 +1386,8 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
tgt = tgt_free;
}
free_winprop(&prop);
}
// Otherwise, just fetch the string list
else {
} else {
// Not an atom type, just fetch the string list
char **strlst = NULL;
int nstr;
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) &&
@@ -1456,8 +1438,10 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
} break;
case C2_L_MPCRE:
#ifdef CONFIG_REGEX_PCRE
*pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
tgt, strlen(tgt), 0, 0, NULL, 0) >= 0);
assert(strlen(tgt) <= INT_MAX);
*pres =
(pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
tgt, (int)strlen(tgt), 0, 0, NULL, 0) >= 0);
#else
assert(0);
#endif