NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/60322: libedit readline compat function history_truncate_file() drops first line cookie
>Number: 60322
>Category: lib
>Synopsis: libedit readline compat function history_truncate_file() drops first line cookie
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 12 05:15:00 +0000 2026
>Originator: Dominique Martinet
>Release: 3.1.20260512
>Organization:
Atmark Techno
>Environment:
produced with libedit portable ( https://thrysoee.dk/editline/ ) at least 3.1.20250104 through 3.1.20260512
>Description:
Calling history_truncate_file() with a non-trivial amount will drop the first line cookie ("_HiStOrY_V2_") from the history file, making the file no longer load afterwards (EINVAL)
This has been reported on postgres mailing lists here:
https://www.postgresql.org/message-id/CALaJbqz262ax%3Dt8W32oujxM%2B5Kn7Ov5nT%2BrZgaJn70CbRroFfQ%40mail.gmail.com
but I've also reproduced the problem with python (cpython) built with editline and running their test suite (see repeat instruction below)
>How-To-Repeat:
Using cpython from their git https://github.com/python/cpython as of a couple of day's ago main branch (84630e2cb90e "gh-136880: Add warning about PYTHONPATH (GH-151098)"):
./configure --with-readline=editline
make
./python ./Lib/test/test_readline.py
should fail in a couple of places including the following
============8<==========
ERROR: test_write_read_limited_history (__main__.TestReadline.test_write_read_limited_history)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".../cpython/./Lib/test/test_readline.py", line 415, in test_write_read_limited_history
readline.read_history_file(TESTFN)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
OSError: [Errno 22] Invalid argument
============8<==========
>Fix:
As a first stopgap measure I've checked that just seeking after the cookie in history_truncate_file() made the problem go away:
============8<==========
diff --git a/src/readline.c b/src/readline.c
index 22e74d3f34c9..2f5ecfbfd164 100644
--- a/src/readline.c
+++ b/src/readline.c
@@ -1384,7 +1384,7 @@ history_truncate_file (const char *filename, int nlines)
if (ret || nlines > 0)
goto out3;
- if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
+ if (fseeko(fp, (off_t)strlen("_HiStOrY_V2_\n"), SEEK_SET) == (off_t)-1) {
ret = errno;
goto out3;
}
============8<==========
But that's not a proper fix, mostly because it just assumes the cookie is there and it hardcodes the value.
I see two obvious ways of dealing with this:
- since the cookie value is not shared (hist_cookie is a static variable in history.c), this code could just always keep the first line in place regardless of its value; it's a bit annoying to track yet another new line here and I'd need to introduce a couple of variables to do it but it's definitely a possibility
- make the hist_cookie variable non-static and use it as is in history_truncate_file(): the easiest fix I can see is keeping seek at 0 and unconditionally write the cookie first (might need to check we're actually truncating the file, or we'd risk having two cookies if count == 0?)
I'll be happy to test and send a patch with either version or anything else if someone has suggestions, or just leave it up to you.
Thanks!
Home |
Main Index |
Thread Index |
Old Index