Package: llvm-gcc-4.2
Version: 2.5-1
Severity: normal

I have found a case where llvm-gcc-4.2 miscompiles code on amd64/sid.
The testcase is attached.  Unfortunately, the testcase requires Qt 4 (I
used 4.5.0 from experimental; I don't know if the version from sid will
work.)  I tried to remove the last dependency on QString from Token, but
when I did, the code no longer failed.  Thus, to compile it, you'll need
to use:

  /usr/lib/llvm/llvm/gcc-4.2/bin/x86_64-linux-gnu-llvm-g++ -O2 -D_REENTRANT 
-DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ 
-I/usr/include/qt4/QtCore -I/usr/include/qt4 -o troff foo.cxx -lQtCore -lpthread

I apologize in advance for this problem.

The bug occurs in TroffReadxer::parseRequestName.  m_compat is set to 4
by the TroffReader constructor.  Therefore, m_compat.getMode() returns
4.  CompatibilityMode::AllowLongNames is 8.  Therefore, maxtoke should
be 2, since (4 & 8) is false.  Instead, maxtoke is set to (size_t)-1.  A
couple of lines down, the code checks for this case and calls abort(3).

If you need anything else, please let me know.

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.29-1-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages llvm-gcc-4.2 depends on:
ii  libc6                         2.9-6      GNU C Library: Shared libraries
ii  libgcc1                       1:4.3.3-5  GCC support library
ii  libstdc++6                    4.3.3-5    The GNU Standard C++ Library v3
ii  llvm                          2.5-2      Low-Level Virtual Machine (LLVM) c
ii  llvm-dev                      2.5-2      common libraries and headers for L

llvm-gcc-4.2 recommends no packages.

Versions of packages llvm-gcc-4.2 suggests:
pn  gcc-4.2-doc                   <none>     (no description available)

-- no debconf information

--
brian m. carlson / brian with sandals: Houston, Texas, US
+1 713 440 7475 | http://crustytoothpaste.ath.cx/~bmc | My opinion only
troff on top of XML: http://crustytoothpaste.ath.cx/~bmc/code/thwack
OpenPGP: RSA v4 4096b 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187
#ifndef THWACK_TROFF_READER_HH
#define THWACK_TROFF_READER_HH

#include <vector>

#ifndef THWACK_TROFF_LEXER_HH
#define THWACK_TROFF_LEXER_HH

#include <cwctype>

#ifndef THWACK_INTERNAL_HH
#define THWACK_INTERNAL_HH

#include <tr1/memory>

#define THWACK_PTR(x) std::tr1::shared_ptr<x>
#define THWACK_CAST(x) std::tr1::dynamic_pointer_cast<x>

#endif

#ifndef THWACK_TROFF_ENVIRONMENT_HH
#define THWACK_TROFF_ENVIRONMENT_HH


#ifndef THWACK_TROFF_TOKEN_HH
#define THWACK_TROFF_TOKEN_HH

#include <QString>
class Token
{
	public:
		enum Type
		{
			Token_Character,
			Token_EOF,
			Token_Escape,
			Token_Newline,
			Token_EOL=Token_Newline,
			Token_Space,
			Token_Whitespace,
			Token_BOL,
			Token_Compatibility
		};
		Token() : m_type(Token_EOF), m_c(0), m_flags(0) {}
		explicit Token(Type t) : m_type(t), m_c(0), m_flags(0) {}
		explicit Token(wchar_t c);
		Token(Type t, int c);
		bool isEOF() const;
		bool isNewline() const;
		bool isSpace() const;
		bool isWhitespace() const;
		bool isTerminal() const;
		bool isEscape() const;
		wchar_t getCharacter() const;
		wchar_t getTextEquivalent() const;
		bool isCharacter() const;
		bool operator==(const Token &a) const;
		bool operator!=(const Token &a) const;
		Type getType() const;
		wchar_t getEscapeType() const;
		int getFlags() const;
	protected:
	private:
		Type m_type;
		wchar_t m_c;
		QString m_name;
		int m_flags;
};
typedef std::vector<Token> TokenString;

#endif

Token::Token(wchar_t c) : m_c(c), m_flags(0)
{
	m_type=std::iswspace(c)?Token_Whitespace:Token_Character;
}
Token::Token(Type t, int c)
{
	if ((m_type=t)==Token_Compatibility)
		m_flags=c;
}
bool Token::isEOF() const
{
	return m_type==Token_EOF;
}
bool Token::isNewline() const
{
	return m_type==Token_Newline || m_type==Token_BOL;
}
bool Token::isSpace() const
{
	return m_type==Token_Space;
}
bool Token::isWhitespace() const
{
	return m_type==Token_Whitespace || isSpace();
}
bool Token::isTerminal() const
{
	return isNewline() || isEOF();
}
bool Token::isEscape() const
{
	return m_type==Token_Escape;
}
wchar_t Token::getCharacter() const
{
	return isCharacter() ? m_c : 0;
}
wchar_t Token::getTextEquivalent() const
{
	return isCharacter() ? m_c :
		(isWhitespace() ? L' ' :
		 (isNewline() ? L'\n' : 0));
}
bool Token::isCharacter() const
{
	return m_type==Token_Character;
}
Token::Type Token::getType() const
{
	return m_type;
}
wchar_t Token::getEscapeType() const
{
	return m_c;
}

#endif

class CompatibilityMode
{
	public:
		// GroffCompatibility means compatibility with groff, not groff
		// compatibility mode.
		enum
		{
			XFlag0=0,
			AllowDo=4,
			XFlag1=AllowDo,
			AllowLongNames=8,
			XFlag2=XFlag1|AllowLongNames,
			NoFallback=16,
			XFlag3=XFlag2|NoFallback,
			GroffCompatibility=32,
			Groff=XFlag3|GroffCompatibility,
			All=Groff
		};
		CompatibilityMode(int thwack=All) : m_cp(thwack) {}
		void setMode(int thwack) { m_cp=thwack; }
		static int lookupGroff(bool val)
		{
			return val ? Groff : XFlag1;
		}
		int getGroff() const { return (m_cp&Groff)==Groff; }
		void setGroff(bool val) { m_cp = lookupGroff(val); }
		static int lookupXFlag(int val)
		{
			const int masks[] = {
				XFlag0, XFlag1, XFlag2, XFlag3
			};
			return masks[(val > 3) ? 3 : ((val < 0) ? 0 : val)];
		}
		int getXFlag() const
		{
			for (int i = 3; i >= 0; i--)
				if ((m_cp & lookupXFlag(i)) == lookupXFlag(i))
					return i;
			return 0;
		}
		void setXFlag(int val)
		{
			m_cp = lookupXFlag(val);
		}
		int getMode() const { return m_cp; }
		int has(int mode) const { return m_cp&mode; }
	private:
		int m_cp;
};
#endif

class Location
{
	public:
		Location(TokenString::iterator c, TokenString::iterator l,
				TokenString::iterator f) :
			m_cur(c), m_eol(l), m_eof(f) {}
		virtual TokenString::iterator &cur()
		{
			return m_cur;
		}
		virtual TokenString::iterator &eol()
		{
			return m_eol;
		}
		virtual TokenString::iterator &eof()
		{
			return m_eof;
		}
	protected:
		Location() {}
		TokenString::iterator m_cur, m_eol, m_eof;
	private:
};

class TroffReader
{
	public:
		TroffReader();
		void parse(void);
	protected:
		void switchCompatibilityMode(CompatibilityMode cm);
		void parseOneLine(Location &);
		void parseRequestName(Location &loc);
	private:
		CompatibilityMode m_compat;
};


#endif

int main(void)
{
	TroffReader rdr;
	rdr.parse();

	return 0;
}
TroffReader::TroffReader() 
{
	m_compat = CompatibilityMode(4);
	switchCompatibilityMode(m_compat);
}
/* This function looks up strings, macros, and diversions; they are all handled
 * similarly.
 */
void TroffReader::switchCompatibilityMode(CompatibilityMode cm)
{
	m_compat=cm;
}
void TroffReader::parseOneLine(Location &loc)
{
	wchar_t c=loc.cur()->getCharacter();
	if (c == '.') {
		loc.cur()++;
		parseRequestName(loc);
	}
}
// XXX: This is pure.
void TroffReader::parseRequestName(Location &loc)
{
	const size_t maxtoke=
		(m_compat.getMode()&m_compat.AllowLongNames?static_cast<size_t>(-1):2);
	wchar_t c=0;
	Token t;
	if (m_compat.getMode() == 4 && maxtoke != 2)
		abort();
	for (size_t ntoke=0; ntoke<maxtoke && loc.cur()!=loc.eol() &&
			loc.cur() != loc.eof(); ntoke++)
	{
		t=*loc.cur()++;
		c=t.getCharacter();
		if (t.isNewline() || t.isEscape()) {
			// This form of escape handling is for groff compatibility.  For
			// Unix troff compatibility, we should allow this.  Producing
			// sensible semantics may not be easy, though.
			--loc.cur();
			break;
		}
		else if (t.isWhitespace()) {
			break;
		}
	}
}
void TroffReader::parse()
{
	TokenString ts;
	ts.push_back(Token('.'));
	ts.push_back(Token('d'));
	ts.push_back(Token('o'));
	ts.push_back(Token(Token::Token_Whitespace));
	ts.push_back(Token('B'));
	ts.push_back(Token('B'));
	ts.push_back(Token('B'));
	ts.push_back(Token(Token::Token_Newline));
	THWACK_PTR(Location) loc(new Location(ts.begin(), ts.end() , ts.end()));
	for (; loc->cur() != loc->eof();)
		parseOneLine(*loc);
}

Attachment: signature.asc
Description: Digital signature

Reply via email to