Browse Source

* apt-pkg/contrib/error.cc:

- ensure that va_list is not invalid in second try
debian/1.8.y
David Kalnischkies 11 years ago
parent
commit
38f297033f
  1. 169
      apt-pkg/contrib/error.cc
  2. 5
      apt-pkg/contrib/error.h
  3. 8
      debian/changelog
  4. 32
      test/libapt/globalerror_test.cc

169
apt-pkg/contrib/error.cc

@ -58,124 +58,109 @@
// GlobalError::GlobalError - Constructor /*{{{*/
GlobalError::GlobalError() : PendingFlag(false) {}
/*}}}*/
// GlobalError::FatalE - Get part of the error string from errno /*{{{*/
bool GlobalError::FatalE(const char *Function,const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(FATAL, Function, Description, args);
}
/*}}}*/
// GlobalError::Errno - Get part of the error string from errno /*{{{*/
bool GlobalError::Errno(const char *Function,const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(ERROR, Function, Description, args);
}
/*}}}*/
// GlobalError::WarningE - Get part of the warning string from errno /*{{{*/
bool GlobalError::WarningE(const char *Function,const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(WARNING, Function, Description, args);
}
/*}}}*/
// GlobalError::NoticeE - Get part of the notice string from errno /*{{{*/
bool GlobalError::NoticeE(const char *Function,const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(NOTICE, Function, Description, args);
}
/*}}}*/
// GlobalError::DebugE - Get part of the debug string from errno /*{{{*/
bool GlobalError::DebugE(const char *Function,const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(DEBUG, Function, Description, args);
// GlobalError::FatalE, Errno, WarningE, NoticeE and DebugE - Add to the list/*{{{*/
#define GEMessage(NAME, TYPE) \
bool GlobalError::NAME (const char *Function, const char *Description,...) { \
va_list args; \
size_t msgSize = 400; \
int const errsv = errno; \
while (true) { \
va_start(args,Description); \
if (InsertErrno(TYPE, Function, Description, args, errsv, msgSize) == false) \
break; \
va_end(args); \
} \
return false; \
}
GEMessage(FatalE, FATAL)
GEMessage(Errno, ERROR)
GEMessage(WarningE, WARNING)
GEMessage(NoticeE, NOTICE)
GEMessage(DebugE, DEBUG)
#undef GEMessage
/*}}}*/
// GlobalError::InsertErrno - Get part of the errortype string from errno/*{{{*/
bool GlobalError::InsertErrno(MsgType const &type, const char *Function,
const char *Description,...) {
va_list args;
va_start(args,Description);
return InsertErrno(type, Function, Description, args);
size_t msgSize = 400;
int const errsv = errno;
while (true) {
va_start(args,Description);
if (InsertErrno(type, Function, Description, args, errsv, msgSize) == false)
break;
va_end(args);
}
return false;
}
/*}}}*/
// GlobalError::InsertErrno - formats an error message with the errno /*{{{*/
bool GlobalError::InsertErrno(MsgType type, const char* Function,
const char* Description, va_list &args) {
int const errsv = errno;
char* S = (char*) malloc(400);
size_t const Ssize = snprintf(S, 400, "%s - %s (%i: %s)", Description,
Function, errsv, strerror(errsv)) + 1;
if (Ssize > 400) {
free(S);
S = (char*) malloc(Ssize);
snprintf(S, Ssize, "%s - %s (%i: %s)", Description,
Function, errsv, strerror(errsv));
const char* Description, va_list &args,
int const errsv, size_t &msgSize) {
char* S = (char*) malloc(msgSize);
int const n = snprintf(S, msgSize, "%s - %s (%i: %s)", Description,
Function, errsv, strerror(errsv));
if (n > -1 && ((unsigned int) n) < msgSize);
else {
if (n > -1)
msgSize = n + 1;
else
msgSize *= 2;
return true;
}
bool const geins = Insert(type, S, args);
bool const geins = Insert(type, S, args, msgSize);
free(S);
return geins;
}
/*}}}*/
// GlobalError::Fatal - Add a fatal error to the list /*{{{*/
bool GlobalError::Fatal(const char *Description,...) {
va_list args;
va_start(args,Description);
return Insert(FATAL, Description, args);
}
/*}}}*/
// GlobalError::Error - Add an error to the list /*{{{*/
bool GlobalError::Error(const char *Description,...) {
va_list args;
va_start(args,Description);
return Insert(ERROR, Description, args);
}
/*}}}*/
// GlobalError::Warning - Add a warning to the list /*{{{*/
bool GlobalError::Warning(const char *Description,...) {
va_list args;
va_start(args,Description);
return Insert(WARNING, Description, args);
}
/*}}}*/
// GlobalError::Notice - Add a notice to the list /*{{{*/
bool GlobalError::Notice(const char *Description,...)
{
va_list args;
va_start(args,Description);
return Insert(NOTICE, Description, args);
}
/*}}}*/
// GlobalError::Debug - Add a debug to the list /*{{{*/
bool GlobalError::Debug(const char *Description,...)
{
va_list args;
va_start(args,Description);
return Insert(DEBUG, Description, args);
// GlobalError::Fatal, Error, Warning, Notice and Debug - Add to the list/*{{{*/
#define GEMessage(NAME, TYPE) \
bool GlobalError::NAME (const char *Description,...) { \
va_list args; \
size_t msgSize = 400; \
while (true) { \
va_start(args,Description); \
if (Insert(TYPE, Description, args, msgSize) == false) \
break; \
va_end(args); \
} \
return false; \
}
GEMessage(Fatal, FATAL)
GEMessage(Error, ERROR)
GEMessage(Warning, WARNING)
GEMessage(Notice, NOTICE)
GEMessage(Debug, DEBUG)
#undef GEMessage
/*}}}*/
// GlobalError::Insert - Add a errotype message to the list /*{{{*/
bool GlobalError::Insert(MsgType const &type, const char *Description,...)
{
va_list args;
va_start(args,Description);
return Insert(type, Description, args);
size_t msgSize = 400;
while (true) {
va_start(args,Description);
if (Insert(type, Description, args, msgSize) == false)
break;
va_end(args);
}
return false;
}
/*}}}*/
// GlobalError::Insert - Insert a new item at the end /*{{{*/
bool GlobalError::Insert(MsgType type, const char* Description,
va_list &args) {
char* S = (char*) malloc(400);
size_t const Ssize = vsnprintf(S, 400, Description, args) + 1;
if (Ssize > 400) {
free(S);
S = (char*) malloc(Ssize);
vsnprintf(S, Ssize, Description, args);
va_list &args, size_t &msgSize) {
char* S = (char*) malloc(msgSize);
int const n = vsnprintf(S, msgSize, Description, args);
if (n > -1 && ((unsigned int) n) < msgSize);
else {
if (n > -1)
msgSize = n + 1;
else
msgSize *= 2;
return true;
}
Item const m(S, type);

5
apt-pkg/contrib/error.h

@ -307,9 +307,10 @@ private: /*{{{*/
std::list<MsgStack> Stacks;
bool InsertErrno(MsgType type, const char* Function,
const char* Description, va_list &args);
const char* Description, va_list &args,
int const errsv, size_t &msgSize);
bool Insert(MsgType type, const char* Description,
va_list &args);
va_list &args, size_t &msgSize);
/*}}}*/
};
/*}}}*/

8
debian/changelog

@ -1,3 +1,11 @@
apt (0.8.11.4) UNRELEASED; urgency=low
[ David Kalnischkies ]
* apt-pkg/contrib/error.cc:
- ensure that va_list is not invalid in second try
-- David Kalnischkies <kalnischkies@gmail.com> Tue, 15 Feb 2011 13:09:57 +0100
apt (0.8.11.3) unstable; urgency=low
* apt-pkg/contrib/fileutl.cc:

32
test/libapt/globalerror_test.cc

@ -2,6 +2,7 @@
#include "assert.h"
#include <string>
#include <errno.h>
int main(int argc,char *argv[])
{
@ -73,5 +74,36 @@ int main(int argc,char *argv[])
equals(text, "A Warning");
equals(_error->empty(), true);
errno = 0;
equals(_error->Errno("errno", "%s horrible %s %d times", "Something", "happend", 2), false);
equals(_error->empty(), false);
equals(_error->PendingError(), true);
equals(_error->PopMessage(text), true);
equals(_error->PendingError(), false);
equals(text, "Something horrible happend 2 times - errno (0: Success)");
equals(_error->empty(), true);
std::string longText;
for (size_t i = 0; i < 500; ++i)
longText.append("a");
equals(_error->Error("%s horrible %s %d times", longText.c_str(), "happend", 2), false);
equals(_error->PopMessage(text), true);
equals(text, std::string(longText).append(" horrible happend 2 times"));
equals(_error->Errno("errno", "%s horrible %s %d times", longText.c_str(), "happend", 2), false);
equals(_error->PopMessage(text), true);
equals(text, std::string(longText).append(" horrible happend 2 times - errno (0: Success)"));
equals(_error->Warning("Репозиторий не обновлён и будут %d %s", 4, "test"), false);
equals(_error->PopMessage(text), false);
equals(text, "Репозиторий не обновлён и будут 4 test");
longText.clear();
for (size_t i = 0; i < 50; ++i)
longText.append("РезийбёбAZ");
equals(_error->Warning(longText.c_str()), false);
equals(_error->PopMessage(text), false);
equals(text, longText);
return 0;
}

Loading…
Cancel
Save