[Python-checkins] cpython (3.3): Issue #18458: Prevent crashes with newer versions of libedit. Its readline

ned.deily python-checkins at python.org
Sun Oct 13 00:58:15 CEST 2013


http://hg.python.org/cpython/rev/dfb7cab9f819
changeset:   86266:dfb7cab9f819
branch:      3.3
parent:      86259:faf318b53d58
user:        Ned Deily <nad at acm.org>
date:        Sat Oct 12 15:47:58 2013 -0700
summary:
  Issue #18458: Prevent crashes with newer versions of libedit.  Its readline
emulation has changed from 0-based indexing to 1-based like gnu readline.
Original patch by Ronald Oussoren.

files:
  Misc/NEWS          |   4 +++
  Modules/readline.c |  40 +++++++++++++++++++++------------
  2 files changed, 29 insertions(+), 15 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -76,6 +76,10 @@
 Library
 -------
 
+- Issue #18458: Prevent crashes with newer versions of libedit.  Its readline
+  emulation has changed from 0-based indexing to 1-based like gnu readline.
+  Original patch by Ronald Oussoren.
+
 - Issue #18919: If the close() method of a writer in the sunau or wave module
   failed, second invocation of close() and destructor no more raise an
   exception.
diff --git a/Modules/readline.c b/Modules/readline.c
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -54,14 +54,16 @@
  * with the "real" readline and cannot be detected at compile-time,
  * hence we use a runtime check to detect if we're using libedit
  *
- * Currently there is one know API incompatibility:
+ * Currently there is one known API incompatibility:
  * - 'get_history' has a 1-based index with GNU readline, and a 0-based
- *   index with libedit's emulation.
+ *   index with older versions of libedit's emulation.
  * - Note that replace_history and remove_history use a 0-based index
- *   with both implementation.
+ *   with both implementations.
  */
 static int using_libedit_emulation = 0;
 static const char libedit_version_tag[] = "EditLine wrapper";
+
+static int libedit_history_start = 0;
 #endif /* __APPLE__ */
 
 #ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
@@ -579,21 +581,21 @@
         return NULL;
 #ifdef  __APPLE__
     if (using_libedit_emulation) {
-        /* Libedit emulation uses 0-based indexes,
-         * the real one uses 1-based indexes,
-         * adjust the index to ensure that Python
-         * code doesn't have to worry about the
-         * difference.
+        /* Older versions of libedit's readline emulation
+         * use 0-based indexes, while readline and newer
+         * versions of libedit use 1-based indexes.
          */
         int length = _py_get_history_length();
-        idx --;
+
+        idx = idx - 1 + libedit_history_start;
 
         /*
          * Apple's readline emulation crashes when
          * the index is out of range, therefore
          * test for that and fail gracefully.
          */
-        if (idx < 0 || idx >= length) {
+        if (idx < (0 + libedit_history_start)
+                || idx >= (length + libedit_history_start)) {
             Py_RETURN_NONE;
         }
     }
@@ -908,6 +910,17 @@
      */
     if (using_libedit_emulation)
         rl_initialize();
+
+    /* Detect if libedit's readline emulation uses 0-based
+     * indexing or 1-based indexing.
+     */
+    add_history("1");
+    if (history_get(1) == NULL) {
+        libedit_history_start = 0;
+    } else {
+        libedit_history_start = 1;
+    }
+    clear_history();
 #endif /* __APPLE__ */
 
     using_history();
@@ -1116,11 +1129,8 @@
         if (length > 0)
 #ifdef __APPLE__
             if (using_libedit_emulation) {
-                /*
-                 * Libedit's emulation uses 0-based indexes,
-                 * the real readline uses 1-based indexes.
-                 */
-                line = (const char *)history_get(length - 1)->line;
+                /* handle older 0-based or newer 1-based indexing */
+                line = (const char *)history_get(length + libedit_history_start - 1)->line;
             } else
 #endif /* __APPLE__ */
             line = (const char *)history_get(length)->line;

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list