commit 6fd3dd30b0f770da97721851bda47ddea678c1b2
parent f7f1e147b5dbbf34617b8727e53acecbad67c24a
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 8 Jul 2023 11:24:26 +0200
Fix reading out-of-bounds entries + improvements
Diffstat:
M | Makefile | | | 6 | +++--- |
M | tquery.c | | | 81 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
2 files changed, 44 insertions(+), 43 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,9 +1,9 @@
PREFIX ?= /usr/local
BINDIR ?= /bin
-CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -Og -g \
- -Wunused-function -Wunused-variable -Wconversion -Wsign-compare
-LDLIBS = -lcurses
+CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -Og -g -Wunused-function \
+ -Wunused-variable -Wconversion -Wsign-compare -Wuninitialized
+LDFLAGS = -lcurses
all: tquery
diff --git a/tquery.c b/tquery.c
@@ -12,19 +12,24 @@
#include <stdio.h>
#include <stdlib.h>
+#define LOAD_BUFSIZ 16384
+#define INPUT_BUFSIZ 2048
+
#define CTRL(x) ((x) & 0x1f)
#define MIN(a, b) ((a) > (b) ? (b) : (a))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
struct nav {
- int wmin, wmax, wlen;
- int sel, min, max;
+ ssize_t wmin, wmax, wlen;
+ ssize_t sel, min, max;
};
static int child_fd = -1;
static pid_t child_pid = 0;
+static char *loadbuf = NULL;
+
static char *output = NULL;
static size_t output_len = 0;
static size_t output_cap = 0;
@@ -35,7 +40,7 @@ static size_t delims_cap = 0;
static struct nav output_nav;
-static char inputbuf[2048] = { 0 };
+static char *inputbuf = NULL;
static size_t inputlen = 0;
static bool splitargs = false;
@@ -50,12 +55,10 @@ die(const char *fmt, ...)
{
va_list ap;
- /* stdout because of swapped fds */
-
- fputs("tquery: ", stdout);
+ fputs("tquery: ", stderr);
va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
+ vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
@@ -82,20 +85,6 @@ sigint(int sig)
}
static void
-swapfd(int fd1, int fd2)
-{
- int fd, rc;
-
- fd = dup(fd1);
- if (fd < 0) die("dup:");
- rc = dup2(fd2, fd1);
- if (rc == -1) die("dup2:");
- rc = dup2(fd, fd2);
- if (rc == -1) die("dup2:");
- close(fd);
-}
-
-static void
nav_update_win(struct nav *nav)
{
nav->wmin = MAX(nav->wmax - nav->wlen, nav->min);
@@ -123,14 +112,14 @@ nav_update_bounds(struct nav *nav, int min, int max)
}
static void
-nav_update_wlen(struct nav *nav, int wlen)
+nav_update_wlen(struct nav *nav, ssize_t wlen)
{
nav->wlen = wlen;
nav_update_win(nav);
}
static void
-nav_update_sel(struct nav *nav, int sel)
+nav_update_sel(struct nav *nav, ssize_t sel)
{
nav->sel = MAX(MIN(sel, nav->max - 1), nav->min);
if (nav->sel >= nav->wmax) {
@@ -211,7 +200,6 @@ spawn(const char **prefix, const char *query)
if (!child_pid) {
close(0);
if (childerr) {
- swapfd(1, 2);
close(1);
} else {
close(1);
@@ -274,12 +262,11 @@ addcap(void *alloc, size_t dsize, size_t min, size_t *cap)
static void
load(void)
{
- char buf[BUFSIZ];
ssize_t nread;
- size_t i, len;
+ size_t i;
char *start;
- nread = read(child_fd, buf, BUFSIZ);
+ nread = read(child_fd, loadbuf, LOAD_BUFSIZ);
if (nread <= 0) {
child_pid = 0;
close(child_fd);
@@ -288,12 +275,11 @@ load(void)
}
output = addcap(output, 1, output_len + (size_t) nread, &output_cap);
- memcpy(output + output_len, buf, (size_t) nread);
+ memcpy(output + output_len, loadbuf, (size_t) nread);
start = output + output_len;
- output_len += (size_t) nread;
- for (i = len; i < len + (size_t) nread; i++, start++) {
+ for (i = output_len; i < output_len + (size_t) nread; i++, start++) {
if (*start == delim) {
*start = '\0';
delims = addcap(delims, sizeof(size_t),
@@ -301,6 +287,8 @@ load(void)
delims[delims_len++] = i;
}
}
+
+ output_len += (size_t) nread;
}
static char *
@@ -321,13 +309,14 @@ update(void)
width = getmaxx(stdscr);
height = getmaxy(stdscr);
- mvprintw(1, 1, "%lu %lu %i", output_len, delims_len, child_pid);
+ mvprintw(1, 1, "%lu %li %lu %i", output_len,
+ output_nav.sel, delims_len, child_pid);
mvprintw(2, 1, "> %.*s", width - 1, inputbuf);
- if (output_len) {
- nav_update_bounds(&output_nav, 0, (int) delims_len);
- nav_update_wlen(&output_nav, (int) (height - miny));
+ nav_update_bounds(&output_nav, 0, (int) delims_len);
+ nav_update_wlen(&output_nav, (int) (height - miny));
+ if (output_len) {
i = output_nav.wmin;
for (y = miny; y < height && i < output_nav.wmax; y++, i++) {
if (i == output_nav.sel)
@@ -397,8 +386,16 @@ input(void)
clear();
dirty = true;
break;
+ case CTRL('b'):
+ nav_update_sel(&output_nav, output_nav.min);
+ dirty = true;
+ break;
+ case CTRL('g'):
+ nav_update_sel(&output_nav, output_nav.max-1);
+ dirty = true;
+ break;
case '\n':
- if (output_nav.sel >= 0) {
+ if (output_nav.max > 0 && output_nav.sel >= 0) {
fputs(entry((size_t) output_nav.sel), stderr);
if (single) exit(0);
}
@@ -462,9 +459,8 @@ parse(int argc, const char **argv)
}
}
- if (!child_argv || !*child_argv) {
+ if (!child_argv || !*child_argv)
usage(0, false);
- }
if (*child_argv[0] != '/' && strncmp(child_argv[0], "./", 2)) {
cmd_path = findbin(child_argv[0]);
@@ -481,14 +477,13 @@ main(int argc, const char **argv)
parse(argc, argv);
- swapfd(1, 2);
-
nav_init(&output_nav);
signal(SIGINT, sigint);
atexit((void (*)()) endwin);
- initscr();
+ if (!newterm(NULL, stderr, stdin))
+ die("newterm stdin -> stderr");
cbreak();
noecho();
keypad(stdscr, true);
@@ -499,6 +494,12 @@ main(int argc, const char **argv)
spawn(child_argv, "");
+ inputbuf = malloc(INPUT_BUFSIZ);
+ if (!inputbuf) die("malloc inputbuf:");
+
+ loadbuf = malloc(LOAD_BUFSIZ);
+ if (!loadbuf) die("malloc loadbuf:");
+
inputlen = 0;
while (1) {
maxfd = 0;