Merge pull request #2277 from ianyfan/config-read-fix

Fix config buffer overflow and logic
This commit is contained in:
Drew DeVault 2018-07-15 11:55:51 -07:00 committed by GitHub
commit 87334dbccb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -560,16 +560,21 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
bool read_config(FILE *file, struct sway_config *config) { bool read_config(FILE *file, struct sway_config *config) {
bool reading_main_config = false; bool reading_main_config = false;
char *this_config = NULL, *config_pos; char *this_config = NULL;
long config_size = 0; size_t config_size = 0;
if (config->current_config == NULL) { if (config->current_config == NULL) {
reading_main_config = true; reading_main_config = true;
fseek(file, 0, SEEK_END); int ret_seek = fseek(file, 0, SEEK_END);
config_size = ftell(file); long ret_tell = ftell(file);
if (ret_seek == -1 || ret_tell == -1) {
wlr_log(WLR_ERROR, "Unable to get size of config file");
return false;
}
config_size = ret_tell;
rewind(file); rewind(file);
config_pos = this_config = malloc(config_size + 1); config->current_config = this_config = calloc(1, config_size + 1);
if (this_config == NULL) { if (this_config == NULL) {
wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents");
return false; return false;
@ -580,6 +585,7 @@ bool read_config(FILE *file, struct sway_config *config) {
int line_number = 0; int line_number = 0;
char *line; char *line;
list_t *stack = create_list(); list_t *stack = create_list();
size_t read = 0;
while (!feof(file)) { while (!feof(file)) {
char *block = stack->length ? stack->items[0] : NULL; char *block = stack->length ? stack->items[0] : NULL;
line = read_line(file); line = read_line(file);
@ -590,10 +596,21 @@ bool read_config(FILE *file, struct sway_config *config) {
wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line);
if (reading_main_config) { if (reading_main_config) {
size_t l = strlen(line); size_t length = strlen(line);
memcpy(config_pos, line, l); // don't copy terminating character
config_pos += l; if (read + length > config_size) {
*config_pos++ = '\n'; wlr_log(WLR_ERROR, "Config file changed during reading");
list_foreach(stack, free);
list_free(stack);
free(line);
return false;
}
strcpy(this_config + read, line);
if (line_number != 1) {
this_config[read - 1] = '\n';
}
read += length + 1;
} }
line = strip_whitespace(line); line = strip_whitespace(line);
@ -616,7 +633,6 @@ bool read_config(FILE *file, struct sway_config *config) {
list_foreach(stack, free); list_foreach(stack, free);
list_free(stack); list_free(stack);
free(line); free(line);
free(this_config);
return false; return false;
} }
wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); wlr_log(WLR_DEBUG, "Expanded line: %s", expanded);
@ -677,10 +693,6 @@ bool read_config(FILE *file, struct sway_config *config) {
list_foreach(stack, free); list_foreach(stack, free);
list_free(stack); list_free(stack);
if (reading_main_config) {
this_config[config_size - 1] = '\0';
config->current_config = this_config;
}
return success; return success;
} }