Package: aptitude Version: 0.2.15.9-2 aptitude sometimes goes into an endless loop.
problem is the implementation of prompt_sting in src/cmdline/cmdline_prompt.cc line 263 ... static string prompt_string() { string rval; char buf[1024]; cin.getline(buf, 1023); rval+=buf; while(!cin) { cin.getline(buf, 1023); rval+=buf; } return rval; } to excercise the problem, here is a stripped down and slightly modified version of that function, including example output: =========================================================== #include <string> #include <iostream> using namespace std; static string prompt_string_buggy() { string rval; char buf[2]; cin.getline(buf, 2); rval+=buf; cerr << " :" << rval << endl; while(!cin) { static int i = 0; if (i++ > 10) { cerr << "looping... exiting!" << endl; exit(1); } cin.getline(buf, 2); rval+=buf; cerr << " :" << rval << endl; } return rval; } int main(int argc, char** argv) { cout << "input??" << endl; cout << prompt_string_buggy(); return 0; } =========================================================== compile that into "prove-bug". then, do Bug Example 1: ./prove-bug < /dev/null input?? : : : : : : : : : : : : looping... exiting! Bug Example 2: echo 1234 | ./prove-bug input?? :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 looping... exiting! whether the library implementation of getline is correct in not adjusting the offset (bug example 2), I don't know. this might be a different bug. clearly the current implementation does not what is intended in the corner cases of end-of-file or very-long-input. a simple fix is to simply use the global getline(istream cin,string rval); instead of that looping construct... similar at the other places where prompt_string() or cin.getline() is used. my suggested patch is this: ================================================================== diff -ru aptitude-0.2.15.9/src/cmdline/cmdline_prompt.cc aptitude-0.2.15.9_fixed/src/cmdline/cmdline_prompt.cc --- aptitude-0.2.15.9/src/cmdline/cmdline_prompt.cc 2006-02-11 11:25:00.000000000 +0100 +++ aptitude-0.2.15.9_fixed/src/cmdline/cmdline_prompt.cc 2006-02-11 12:46:07.000000000 +0100 @@ -258,24 +258,6 @@ N_("The following packages will be upgraded:"), }; -// Probably something like cin.getline() would work, but I don't trust that -// for interactive use. -static string prompt_string() -{ - string rval; - char buf[1024]; - cin.getline(buf, 1023); - rval+=buf; - - while(!cin) - { - cin.getline(buf, 1023); - rval+=buf; - } - - return rval; -} - /** Checks for broken/deleted essential packages and displays a big * fat warning message about them. Returns false if the user doesn't * want to continue. @@ -326,15 +308,12 @@ printf(_("WARNING: Performing this action will probably cause your system to break!\n Do NOT continue unless you know EXACTLY what you are doing!\n")); string prompt=_("I am aware that this is a very bad idea"); - char buf[1024]; + string buf; printf(_("To continue, type the phrase \"%s\":\n"), prompt.c_str()); - cin.getline(buf, 1023); + getline(cin,buf); bool rval=(prompt==buf); - while(!cin) - cin.getline(buf, 1023); - return rval; } @@ -383,12 +362,15 @@ { printf(_("Do you want to ignore this warning and proceed anyway?\n")); printf(_("To continue, enter \"%s\"; to abort, enter \"%s\": "), okstr.c_str(), abortstr.c_str()); - char buf[1024]; - cin.getline(buf, 1023); - buf[1023]='\0'; + string buf; + getline(cin,buf); + + // io-error or end-of-file: do not continue. + if(cin.fail() || cin.eof()) + return false; - const bool is_ok=(strncasecmp(okstr.c_str(), buf, okstr.size())==0); - const bool is_abort=(strncasecmp(abortstr.c_str(), buf, abortstr.size())==0); + const bool is_ok=(strncasecmp(okstr.c_str(), buf.c_str(), okstr.size())==0); + const bool is_abort=(strncasecmp(abortstr.c_str(), buf.c_str(), abortstr.size())==0); const bool rval=is_ok; @@ -663,7 +645,8 @@ printf(_("No packages to show -- enter the package names on the line after 'i'.\n")); printf(_("Press Return to continue.")); - prompt_string(); + string sink; + getline(cin,sink); } // Erm. Merge w/ above? @@ -694,7 +677,8 @@ do_cmdline_changelog(packages); printf(_("Press Return to continue.")); - prompt_string(); + string sink; + getline(cin,sink); } bool cmdline_do_prompt(bool as_upgrade, @@ -732,9 +716,14 @@ printf(_("Do you want to continue? [Y/n/?] ")); fflush(stdout); - string response=prompt_string(); - string::size_type loc=0; + string response; + getline(cin,response); + + // io-error or end-of-file: do not continue. + if(cin.fail() || cin.eof()) + return false; + string::size_type loc=0; while(loc<response.size() && isspace(response[loc])) ++loc; ================================================================== Thanks, -- : Lars Ellenberg Tel +43-1-8178292-55 : : LINBIT Information Technologies GmbH Fax +43-1-8178292-82 : : Schoenbrunner Str. 244, A-1120 Vienna/Europe http://www.linbit.com : -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]