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]