summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2016-05-10 10:49:37 +0000
committerschwarze <schwarze@openbsd.org>2016-05-10 10:49:37 +0000
commitdddc8490d90a7478ec6b2430fb09b5626543ec88 (patch)
tree28e152b4bd7def28fba67dde2d9817e4775d970e
parenttypo in comment (diff)
downloadwireguard-openbsd-dddc8490d90a7478ec6b2430fb09b5626543ec88.tar.xz
wireguard-openbsd-dddc8490d90a7478ec6b2430fb09b5626543ec88.zip
Fix history_get():
* Respect history_base. * Bail out early for arguments that are too small. * Select entry by readline offset, not by editline event number. * Restore history cursor in case of failure. This fixes the test_remove() regression test. Based on a patch from Bastian Maerkisch <bmaerkisch at web dot de>. Dmitrij Czarkoff pointed out a flaw in it that i fixed. OK czarkoff@.
-rw-r--r--lib/libedit/readline.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/libedit/readline.c b/lib/libedit/readline.c
index 853d3c9c4c4..3fae304361c 100644
--- a/lib/libedit/readline.c
+++ b/lib/libedit/readline.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readline.c,v 1.24 2016/05/09 12:31:55 schwarze Exp $ */
+/* $OpenBSD: readline.c,v 1.25 2016/05/10 10:49:37 schwarze Exp $ */
/* $NetBSD: readline.c,v 1.91 2010/08/28 15:44:59 christos Exp $ */
/*-
@@ -1358,25 +1358,37 @@ history_get(int num)
if (h == NULL || e == NULL)
rl_initialize();
+ if (num < history_base)
+ return NULL;
+
/* save current position */
if (history(h, &ev, H_CURR) != 0)
return NULL;
curr_num = ev.num;
- /* start from the oldest */
- if (history(h, &ev, H_LAST) != 0)
- return NULL; /* error */
-
- /* look forwards for event matching specified offset */
- if (history(h, &ev, H_NEXT_EVDATA, num, &she.data))
- return NULL;
+ /*
+ * use H_DELDATA to set to nth history (without delete) by passing
+ * (void **)-1 -- as in history_set_pos
+ */
+ if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
+ goto out;
+ /* get current entry */
+ if (history(h, &ev, H_CURR) != 0)
+ goto out;
+ if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
+ goto out;
she.line = ev.str;
/* restore pointer to where it was */
(void)history(h, &ev, H_SET, curr_num);
return &she;
+
+out:
+ /* restore pointer to where it was */
+ (void)history(h, &ev, H_SET, curr_num);
+ return NULL;
}