Add export to OcXmlLib

This commit is contained in:
vit9696 2019-03-16 14:53:24 +03:00
parent c43916be47
commit 9ce5f7b29d
7 changed files with 256 additions and 11 deletions

4
.gitignore vendored
View File

@ -2,8 +2,10 @@
UDK
Binaries
*.dSYM
TestsUser/Serialized/Serialized
TestsUser/Macho/Macho
TestsUser/Prelinked/Prelinked
TestsUser/Prelinked/Result.xml
TestsUser/Serialized/Serialized
TestsUser/Smbios/Smbios
DICT
fuzz-*.log

View File

@ -116,11 +116,25 @@ typedef struct XML_NODE_ XML_NODE;
// @return The parsed xml fragment iff parsing was successful, 0 otherwise
//
XML_DOCUMENT *
XmlParseDocument (
XmlDocumentParse (
CHAR8 *Buffer,
UINT32 Length
);
//
// Exports parsed document into the buffer.
//
// @param Document XML_DOCUMENT to export
// @param Length Resulting length of the buffer without trailing \0 (optional)
//
// @return Exported buffer allocated from pool or NULL.
//
CHAR8 *
XmlDocumentExport (
XML_DOCUMENT *Document,
UINT32 *Length
);
//
// Frees all resources associated with the document. All XML_NODE
// references obtained through the document will be invalidated.

View File

@ -84,7 +84,7 @@ GetAppleRecoveryNameFromPlist (
CHAR16 *RecoveryName;
UINTN RecoveryNameSize;
Document = XmlParseDocument (SystemVersionData, (UINT32) SystemVersionDataSize);
Document = XmlDocumentParse (SystemVersionData, (UINT32) SystemVersionDataSize);
if (Document == NULL) {
return NULL;

View File

@ -311,7 +311,7 @@ ParseSerialized (
XML_DOCUMENT *Document;
XML_NODE *RootDict;
Document = XmlParseDocument (PlistBuffer, PlistSize);
Document = XmlDocumentParse (PlistBuffer, PlistSize);
if (Document == NULL) {
DEBUG ((DEBUG_INFO, "Couldn't parse serialized file!\n"));

View File

@ -47,6 +47,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/OcMiscLib.h>
#include <Library/OcStringLib.h>
//
// Minimal extra allocation size during export.
//
#define XML_EXPORT_MIN_ALLOCATION_SIZE 4096
struct XML_NODE_LIST_;
struct XML_PARSER_;
@ -54,8 +59,8 @@ typedef struct XML_NODE_LIST_ XML_NODE_LIST;
typedef struct XML_PARSER_ XML_PARSER;
//
// An XML_NODE will always contain a tag name and a 0-terminated list of
// children. Moreover it may contain text content.
// An XML_NODE will always contain a tag name and possibly a list of
// children or text content.
//
struct XML_NODE_ {
CONST CHAR8 *Name;
@ -295,7 +300,7 @@ XmlParserError (
#define XML_PARSER_ERROR(Parser, Offset, Message) \
XmlParserError (Parser, Offset, Message)
#define XML_USAGE_ERROR(Message) \
DEBUG ((DEBUG_VERBOSE, "XML_PARSER_TAG %a\n", Message));
DEBUG ((DEBUG_VERBOSE, "%a\n", Message));
#else
#define XML_PARSER_ERROR(Parser, Offset, Message) do {} while (0)
#define XML_USAGE_ERROR(X) do {} while (0)
@ -655,6 +660,86 @@ XmlParseContent (
return &Parser->Buffer[Start];
}
//
// Prints to growing buffer always preserving one byte extra.
//
STATIC
VOID
XmlBufferAppend (
CHAR8 **Buffer,
UINT32 *AllocSize,
UINT32 *CurrentSize,
CONST CHAR8 *Data,
UINT32 DataLength
)
{
CHAR8 *NewBuffer;
UINT32 NewSize;
NewSize = *AllocSize;
if (NewSize - *CurrentSize <= DataLength) {
if (DataLength + 1 <= XML_EXPORT_MIN_ALLOCATION_SIZE) {
NewSize += XML_EXPORT_MIN_ALLOCATION_SIZE;
} else {
NewSize += DataLength + 1;
}
NewBuffer = AllocatePool (NewSize);
if (NewBuffer == NULL) {
XML_USAGE_ERROR("XmlBufferAppend::failed to allocate");
return;
}
CopyMem (NewBuffer, *Buffer, *CurrentSize);
FreePool (*Buffer);
*Buffer = NewBuffer;
*AllocSize = NewSize;
}
CopyMem (&(*Buffer)[*CurrentSize], Data, DataLength);
*CurrentSize += DataLength;
}
//
// Prints node to growing buffer always preserving one byte extra.
//
STATIC
VOID
XmlNodeExportRecursive (
XML_NODE *Node,
CHAR8 **Buffer,
UINT32 *AllocSize,
UINT32 *CurrentSize
)
{
UINT32 Index;
UINT32 NameLength;
NameLength = AsciiStrLen (Node->Name);
XmlBufferAppend (Buffer, AllocSize, CurrentSize, "<", L_STR_LEN ("<"));
XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Name, NameLength);
if (Node->Children != NULL || Node->Content != NULL) {
XmlBufferAppend (Buffer, AllocSize, CurrentSize, ">", L_STR_LEN (">"));
if (Node->Children != NULL) {
for (Index = 0; Index < Node->Children->NodeCount; ++Index) {
XmlNodeExportRecursive (Node->Children->NodeList[Index], Buffer, AllocSize, CurrentSize);
}
} else {
XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Content, AsciiStrLen (Node->Content));
}
XmlBufferAppend (Buffer, AllocSize, CurrentSize, "</", L_STR_LEN ("</"));
XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Name, NameLength);
XmlBufferAppend (Buffer, AllocSize, CurrentSize, ">", L_STR_LEN (">"));
} else {
XmlBufferAppend (Buffer, AllocSize, CurrentSize, "/>", L_STR_LEN ("/>"));
}
}
//
// Parses an XML fragment node.
//
@ -789,7 +874,7 @@ XmlParseNode (
}
XML_DOCUMENT *
XmlParseDocument (
XmlDocumentParse (
CHAR8 *Buffer,
UINT32 Length
)
@ -809,7 +894,7 @@ XmlParseDocument (
// An empty buffer can never contain a valid document.
//
if (Length == 0 || Length > XML_PARSER_MAX_SIZE) {
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlParseDocument::length is too small or too large");
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::length is too small or too large");
return NULL;
}
@ -818,7 +903,7 @@ XmlParseDocument (
//
Root = XmlParseNode (&Parser);
if (Root == NULL) {
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlParseDocument::parsing document failed");
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::parsing document failed");
return NULL;
}
@ -828,7 +913,7 @@ XmlParseDocument (
Document = AllocatePool (sizeof(XML_DOCUMENT));
if (Document == NULL) {
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlParseDocument::document allocation failed");
XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::document allocation failed");
XmlNodeFree (Root);
return NULL;
}
@ -840,6 +925,38 @@ XmlParseDocument (
return Document;
}
CHAR8 *
XmlDocumentExport (
XML_DOCUMENT *Document,
UINT32 *Length
)
{
CHAR8 *Buffer;
UINT32 AllocSize;
UINT32 CurrentSize;
AllocSize = Document->Buffer.Length + 1;
Buffer = AllocatePool (AllocSize);
if (Buffer == NULL) {
XML_USAGE_ERROR ("XmlDocumentExport::failed to allocate");
return NULL;
}
CurrentSize = 0;
XmlNodeExportRecursive (Document->Root, &Buffer, &AllocSize, &CurrentSize);
if (Length != NULL) {
*Length = CurrentSize;
}
//
// XmlBufferAppend guarantees one more byte.
//
Buffer[CurrentSize] = '\0';
return Buffer;
}
VOID
XmlDocumentFree (
XML_DOCUMENT *Document

View File

@ -0,0 +1,108 @@
/** @file
Copyright (C) 2018, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/OcTemplateLib.h>
#include <Library/OcSerializeLib.h>
#include <Library/OcMiscLib.h>
#include <sys/time.h>
/*
clang -g -fsanitize=undefined,address -I../Include -I../../Include -I../../../MdePkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c -o Prelinked
for fuzzing:
clang-mp-7.0 -Dmain=__main -g -fsanitize=undefined,address,fuzzer -I../Include -I../../Include -I../../../MdePkg/Include/ -include ../Include/Base.h Prelinked.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c -o Prelinked
rm -rf DICT fuzz*.log ; mkdir DICT ; cp Prelinked.plist DICT ; ./Prelinked -jobs=4 DICT
rm -rf Prelinked.dSYM DICT fuzz*.log Prelinked
*/
long long current_timestamp() {
struct timeval te;
gettimeofday(&te, NULL); // get current time
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds
// printf("milliseconds: %lld\n", milliseconds);
return milliseconds;
}
uint8_t *readFile(const char *str, uint32_t *size) {
FILE *f = fopen(str, "rb");
if (!f) return NULL;
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *string = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
string[fsize] = 0;
*size = fsize;
return string;
}
int main(int argc, char** argv) {
uint32_t f;
uint8_t *b;
if ((b = readFile(argc > 1 ? argv[1] : "Prelinked.xml", &f)) == NULL) {
printf("Read fail\n");
return -1;
}
XML_DOCUMENT *doc = XmlDocumentParse((char *)b, f);
if (doc == NULL) {
printf("Parse fail\n");
return -2;
}
UINT32 s;
CHAR8 *buf = XmlDocumentExport(doc, &s);
if (buf != NULL) {
printf("Exported into %u bytes:\n\n\n", s);
printf("%s\n", buf);
FreePool (buf);
} else {
printf("Exporting gave NULL\n");
}
XmlDocumentFree (doc);
free(b);
return 0;
}
INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) {
VOID *NewData = AllocatePool (Size);
if (NewData) {
CopyMem (NewData, Data, Size);
XML_DOCUMENT *doc = XmlDocumentParse((char *)NewData, Size);
if (doc != NULL) {
UINT32 s;
CHAR8 *buf = XmlDocumentExport(doc, &s);
if (buf != NULL) {
FreePool (buf);
}
XmlDocumentFree (doc);
}
FreePool (NewData);
}
return 0;
}

File diff suppressed because one or more lines are too long