]> granicus.if.org Git - python/commitdiff
[2.7] bpo-29854: Fix segfault in call_readline() (GH-728)
authorNir Soffer <nirsof@gmail.com>
Mon, 10 Jul 2017 21:06:57 +0000 (00:06 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Mon, 10 Jul 2017 21:06:57 +0000 (00:06 +0300)
If history-length is set in .inputrc, and the history file is double the
history size (or more), history_get(N) returns NULL, and python
segfaults. Fix that by checking for NULL return value.

It seems that the root cause is incorrect handling of bigger history in
readline, but Python should not segfault even if readline returns
unexpected value.

This issue affects only GNU readline. When using libedit emulation
system history size option does not work.

This is a backport of the actual fix from master without the test, since
the test depends on new run_pty() helper which is not available in 2.7.

Misc/NEWS.d/next/Library/2017-07-07-02-18-57.bpo-29854.J8wKb_.rst [new file with mode: 0644]
Modules/readline.c

diff --git a/Misc/NEWS.d/next/Library/2017-07-07-02-18-57.bpo-29854.J8wKb_.rst b/Misc/NEWS.d/next/Library/2017-07-07-02-18-57.bpo-29854.J8wKb_.rst
new file mode 100644 (file)
index 0000000..5c43908
--- /dev/null
@@ -0,0 +1,2 @@
+Fix segfault in readline when using readline's history-size option.  Patch
+by Nir Soffer.
index ad5903cfb51a54386fe42ed012095a929f04a1ee..1e10dd708b99c038c842c4038a0ab096488babe8 100644 (file)
@@ -1161,15 +1161,17 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
     if (n > 0) {
         const char *line;
         int length = _py_get_history_length();
-        if (length > 0)
+        if (length > 0) {
+            HIST_ENTRY *hist_ent;
 #ifdef __APPLE__
             if (using_libedit_emulation) {
                 /* handle older 0-based or newer 1-based indexing */
-                line = history_get(length + libedit_history_start - 1)->line;
+                hist_ent = history_get(length + libedit_history_start - 1);
             } else
 #endif /* __APPLE__ */
-            line = history_get(length)->line;
-        else
+                hist_ent = history_get(length);
+            line = hist_ent ? hist_ent->line : "";
+        } else
             line = "";
         if (strcmp(p, line))
             add_history(p);