src/test.cxx
src/core/tests/BasicBlockTest.cxx
src/core/tests/FunctionTest.cxx
+ src/core/tests/CommentTest.cxx
${frida_SOURCES}
)
Function* Comment::getLocation() {
return location;
}
+
+void Comment::serialize(QXmlStreamWriter& stream) {
+ stream.writeStartElement("comment");
+
+ stream.writeTextElement("address", QString::number(address, 16));
+ stream.writeTextElement("text", text.c_str());
+
+ stream.writeEndElement(); // "comment"
+}
+
+Comment* Comment::deserialize(QXmlStreamReader& stream, InformationManager* manager, Function* function) {
+ Q_ASSERT(stream.name() == "comment");
+
+ QString text;
+ uint64_t address = 0;
+ Comment* comment;
+
+ while (QXmlStreamReader::NoToken != stream.readNext()) {
+ while (QXmlStreamReader::Characters == stream.tokenType() &&
+ stream.isWhitespace())
+ stream.readNext();
+ if (QXmlStreamReader::EndElement == stream.tokenType())
+ break;
+
+ if(QXmlStreamReader::StartElement != stream.tokenType())
+ return NULL;
+
+ if (stream.name() == "text") {
+ stream.readNext();
+ if (QXmlStreamReader::Characters != stream.tokenType())
+ return NULL;
+
+ text = stream.text().toString();
+ stream.readNext();
+
+ if(QXmlStreamReader::EndElement != stream.tokenType())
+ return NULL;
+ }
+ if (stream.name() == "address") {
+ stream.readNext();
+ if (QXmlStreamReader::Characters != stream.tokenType())
+ return NULL;
+
+ address = stream.text().toULongLong(NULL, 16);
+ stream.readNext();
+
+ if(QXmlStreamReader::EndElement != stream.tokenType())
+ return NULL;
+ }
+ }
+
+ if (address == 0 or text == "")
+ return NULL;
+
+ if (function)
+ comment = manager->newLocalComment(address, function);
+ else
+ comment = manager->newGlobalComment(address);
+
+ comment->text = text.toStdString();
+
+ assert(stream.name() == "comment");
+
+ manager->finishComment(comment);
+ return comment;
+}
+
file.open(QIODevice::ReadOnly);
if(info.name != "binary") {
- QXmlStreamReader reader(&file);
- assert(QXmlStreamReader::StartDocument == reader.readNext());
- assert(QXmlStreamReader::StartElement == reader.readNext());
- Function::deserialize(reader, this);
+ if (info.name.startsWith("comment:")) {
+ QXmlStreamReader reader(&file);
+ auto starttoken = reader.readNext();
+ auto elementtoken = reader.readNext();
+ assert(QXmlStreamReader::StartDocument == starttoken);
+ assert(QXmlStreamReader::StartElement == elementtoken);
+ Comment::deserialize(reader, this);
+ } else {
+ QXmlStreamReader reader(&file);
+ auto starttoken = reader.readNext();
+ auto elementtoken = reader.readNext();
+ assert(QXmlStreamReader::StartDocument == starttoken);
+ assert(QXmlStreamReader::StartElement == elementtoken);
+ Function::deserialize(reader, this);
+ }
}
file.close();
}
stream.writeEndDocument();
outZipFile.close();
}
+ for (auto commentpair : comments) {
+ Comment* comment = commentpair.second;
+ if (!comment->isLocal()) {
+ QuaZipNewInfo zipinfo(QString("comment:%1").arg(comment->getAddress(), 0, 16));
+ zipinfo.setPermissions(static_cast<QFile::Permissions>(0x6444));
+ outZipFile.open(QIODevice::WriteOnly, zipinfo);
+ QXmlStreamWriter stream(&outZipFile);
+ stream.setAutoFormatting(true);
+ stream.setAutoFormattingIndent(-1);
+ stream.writeStartDocument();
+
+ comment->serialize(stream);
+
+ stream.writeEndDocument();
+ outZipFile.close();
+ }
+ }
zip.close();
}
--- /dev/null
+#include <gtest/gtest.h>
+
+#include "gui/qt.hxx"
+#include "core/InformationManager.hxx"
+#include "core/BasicBlock.hxx"
+#include "core/Comment.hxx"
+#include <iostream>
+
+extern char * TEST_DATA_DIRECTORY;
+
+TEST(CommentTest, deserializeValidInstance) {
+ InformationManager manager;
+ QDir directory(QString("%1/%2").arg(TEST_DATA_DIRECTORY,"/core/Comment/valid/"));
+ QStringList filters;
+ filters << "*.xml";
+ directory.setNameFilters(filters);
+
+ for (auto fileinfo : directory.entryInfoList()) {
+ if (false == fileinfo.isFile())
+ continue;
+
+ QFile file(fileinfo.absoluteFilePath());
+ file.open(QFile::ReadOnly | QFile::Text);
+ QXmlStreamReader reader(&file);
+ reader.readNextStartElement();
+
+ Comment* c = Comment::deserialize(reader, &manager);
+ ASSERT_NE((void*)NULL, (void*)c);
+ EXPECT_EQ(fileinfo.baseName().toULongLong(NULL, 16), c->getAddress());
+ }
+}
+
+TEST(CommentTest, deserializeInvalidInstance) {
+ InformationManager manager;
+ QDir directory(QString("%1/%2").arg(TEST_DATA_DIRECTORY,"/core/Comment/invalid/"));
+ QStringList filters;
+ filters << "*.xml";
+ directory.setNameFilters(filters);
+
+ for (auto fileinfo : directory.entryInfoList()) {
+ if (false == fileinfo.isFile())
+ continue;
+
+ QFile file(fileinfo.absoluteFilePath());
+ file.open(QFile::ReadOnly | QFile::Text);
+ QXmlStreamReader reader(&file);
+ reader.readNextStartElement();
+
+ Comment* c = Comment::deserialize(reader, &manager);
+ ASSERT_EQ((void*)NULL, (void*)c);
+ }
+}
+
+TEST(CommentTest, serializeThenDeserializeIsIdentity) {
+ InformationManager manager;
+ Comment* c = manager.newGlobalComment(0x42234223);
+
+ for (QString text : QStringList({"αβγδ", "<test>", "ä"})) {
+ c->setText(text.toStdString());
+
+ QTemporaryFile tmpfile;
+
+ {
+ tmpfile.open();
+ QXmlStreamWriter writer(&tmpfile);
+ c->serialize(writer);
+ }
+ tmpfile.seek(0);
+ {
+ tmpfile.open();
+ QXmlStreamReader reader(&tmpfile);
+ reader.readNextStartElement();
+ Comment* d = Comment::deserialize(reader, &manager);
+ ASSERT_NE((void*)NULL, (void*)d);
+ EXPECT_STREQ(c->getText().c_str(), d->getText().c_str());
+ EXPECT_EQ(0x42234223, d->getAddress());
+ }
+ }
+}
if (global) {
comment = parent->block->getManager()->newGlobalComment(address);
} else {
- comment = parent->block->getManager()->newLocalComment(address, NULL);
+ comment = parent->block->getManager()->newLocalComment(address, (Function*)0x23);
}
comment->setText(dialog.result().toStdString());
parent->block->getManager()->finishComment(comment);
QString comments;
for (Comment* c: inst->comments()) {
comments += "<br />";
- comments += c->getText().c_str();
+ comments += QString(c->getText().c_str()).toHtmlEscaped();
}
return (comments == "" ? "" : ";; ") + comments.trimmed();
}
--- /dev/null
+<comment>
+ <adress>400580</adress>
+ <text><test> ist auch ein test!! &wasaucheimmer;</text>
+</comment>
--- /dev/null
+<comment>
+ <address>400580</address>
+ <text><test> ist auch ein test!! &wasaucheimmer;</text>
+ <cow>SuperCowPowers!</cow>
+</comment>
--- /dev/null
+<comment>
+ <text><test> ist auch ein test!! &wasaucheimmer;</text>
+</comment>
--- /dev/null
+<comment>
+ <address>400580</address>
+</comment>
--- /dev/null
+<comment>
+ <adress>400580</adress>
+ <text><test> ist auch ein test!! &wasaucheimmer;</text>
+</comment>
--- /dev/null
+<comment>
+ <address>400580</address>
+ <text><test> ist auch ein test!! &wasaucheimmer;</text>
+</comment>