(original) (raw)
changeset: 85581:b6b8a2171aa3 user: Ned Deily nad@acm.org date: Fri Sep 06 15:16:19 2013 -0700 files: Misc/NEWS Modules/readline.c description: 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. diff -r 4b64166d5abb -r b6b8a2171aa3 Misc/NEWS --- a/Misc/NEWS Fri Sep 06 15:42:47 2013 -0500 +++ b/Misc/NEWS Fri Sep 06 15:16:19 2013 -0700 @@ -56,6 +56,9 @@ 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. + - Issue #18852: Handle case of ``readline.__doc__`` being ``None`` in the new readline activation code in ``site.py``. diff -r 4b64166d5abb -r b6b8a2171aa3 Modules/readline.c --- a/Modules/readline.c Fri Sep 06 15:42:47 2013 -0500 +++ b/Modules/readline.c Fri Sep 06 15:16:19 2013 -0700 @@ -63,6 +63,8 @@ */ 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 @@ -627,21 +629,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; } } @@ -974,6 +976,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(); @@ -1178,11 +1191,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; /nad@acm.org