Skip to content

Commit 2c993f9

Browse files
Peter Schrammelpeterschrammel
Peter Schrammel
authored andcommitted
output-repair tool to fix truncated XML and JSON log files
1 parent 05c8580 commit 2c993f9

File tree

7 files changed

+374
-2
lines changed

7 files changed

+374
-2
lines changed

src/Makefile

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ DIRS = ansi-c big-int cbmc cpp goto-cc goto-instrument goto-programs \
22
goto-symex langapi pointer-analysis solvers util linking xmllang \
33
assembler analyses java_bytecode aa-path-symex path-symex musketeer \
44
json cegis goto-analyzer jsil symex goto-diff aa-symex clobber \
5-
memory-models
5+
memory-models output-repair
66

7-
all: cbmc.dir goto-cc.dir goto-instrument.dir symex.dir goto-analyzer.dir goto-diff.dir
7+
all: cbmc.dir goto-cc.dir goto-instrument.dir symex.dir goto-analyzer.dir goto-diff.dir output-repair.dir
88

99
###############################################################################
1010

@@ -46,6 +46,8 @@ symex.dir: languages goto-programs.dir pointer-analysis.dir \
4646

4747
aa-symex.dir: symex.dir aa-path-symex.dir
4848

49+
output-repair.dir:
50+
4951
# building for a particular directory
5052

5153
$(patsubst %, %.dir, $(DIRS)):

src/output-repair/Makefile

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
SRC = output_repair.cpp xml_repair.cpp json_repair.cpp ../util/unicode.cpp
2+
3+
OBJ +=
4+
5+
INCLUDES= -I ..
6+
7+
LIBS =
8+
9+
CLEANFILES = output-repair$(EXEEXT)
10+
11+
include ../config.inc
12+
include ../common
13+
14+
all: output-repair$(EXEEXT)
15+
16+
###############################################################################
17+
18+
output-repair$(EXEEXT): $(OBJ)
19+
$(LINKBIN)
20+
21+
.PHONY: output-repair-mac-signed
22+
23+
output-repair-mac-signed: output-repair$(EXEEXT)
24+
codesign -v -s $(OSX_IDENTITY) output-repair$(EXEEXT)
25+

src/output-repair/json_repair.cpp

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*******************************************************************\
2+
3+
Module: JSON repair tool
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
#include <fstream>
10+
#include <iostream>
11+
#include <stack>
12+
#include <sstream>
13+
14+
#include <util/unicode.h>
15+
16+
#include "json_repair.h"
17+
18+
// cut non-closed branches at this level
19+
#define BACKTRACK_LEVEL 2
20+
21+
/*******************************************************************\
22+
23+
Function: json_repair
24+
25+
Inputs:
26+
27+
Outputs:
28+
29+
Purpose:
30+
31+
\*******************************************************************/
32+
33+
void json_repair(std::ifstream &infile, std::ofstream &outfile)
34+
{
35+
std::stack<bool> elements; // element stack (object=true)
36+
bool instring=false; // within a string
37+
char c, lastc=' '; // current and last character
38+
std::stringstream backtrackbuffer; // buffer for cutting branches
39+
40+
while(infile >> std::noskipws >> c)
41+
{
42+
backtrackbuffer << c;
43+
switch(c)
44+
{
45+
case '[':
46+
if(!instring)
47+
elements.push(false);
48+
break;
49+
case '{':
50+
if(!instring)
51+
elements.push(true);
52+
break;
53+
case '"':
54+
if(lastc!='\\')
55+
instring=!instring;
56+
break;
57+
case ']':
58+
case '}':
59+
if(!instring)
60+
{
61+
if(elements.size()<=BACKTRACK_LEVEL)
62+
{
63+
// at this level everything in the buffer is part of the output
64+
outfile << backtrackbuffer.str();
65+
// clear buffer
66+
backtrackbuffer.seekp(0);
67+
backtrackbuffer.seekg(0);
68+
backtrackbuffer.str("");
69+
backtrackbuffer.clear();
70+
}
71+
elements.pop();
72+
if(elements.empty()) // cut trailing garbage
73+
return;
74+
}
75+
break;
76+
default: break;
77+
}
78+
lastc=c;
79+
}
80+
81+
// everything above BACKTRACK_LEVEL is discarded
82+
// now, add missing closing elements below it:
83+
while(!elements.empty())
84+
{
85+
if(elements.size()<BACKTRACK_LEVEL)
86+
{
87+
outfile << (elements.top() ? "}": "]") << std::endl;
88+
}
89+
elements.pop();
90+
}
91+
}

src/output-repair/json_repair.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*******************************************************************\
2+
3+
Module: JSON repair tool
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_OUTPUT_REPAIR_JSON_REPAIR_H
10+
#define CPROVER_OUTPUT_REPAIR_JSON_REPAIR_H
11+
12+
#include <fstream>
13+
14+
void json_repair(std::ifstream &infile, std::ofstream &outfile);
15+
16+
#endif // CPROVER_OUTPUT_REPAIR_JSON_REPAIR_H

src/output-repair/output_repair.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*******************************************************************\
2+
3+
Module: Output repair tool
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
#include <iostream>
10+
#include <cassert>
11+
12+
#include "json_repair.h"
13+
#include "xml_repair.h"
14+
15+
/*******************************************************************\
16+
17+
Function: repair
18+
19+
Inputs:
20+
21+
Outputs:
22+
23+
Purpose:
24+
25+
\*******************************************************************/
26+
27+
int repair(const char **argv)
28+
{
29+
std::string first(argv[1]);
30+
std::string last(argv[3]);
31+
bool json=(first=="--json") || (last=="--json");
32+
bool xml=(first=="--xml") || (last=="--xml");
33+
bool is_first=(first=="--json") || (first=="--xml");
34+
35+
std::string infilename(argv[1]);
36+
std::string outfilename(argv[2]);
37+
if(is_first)
38+
{
39+
infilename=std::string(argv[2]);
40+
outfilename=std::string(argv[3]);
41+
}
42+
43+
std::ifstream infile;
44+
infile.open(infilename);
45+
if(!infile.is_open())
46+
{
47+
std::cerr << "Cannot open file '" << infilename << "'" << "\n\n";
48+
return -1;
49+
}
50+
51+
std::ofstream outfile;
52+
outfile.open(outfilename);
53+
if(!outfile.is_open())
54+
{
55+
std::cerr << "Cannot open file '" << outfilename << "'" << "\n\n";
56+
return -1;
57+
}
58+
59+
if(json)
60+
json_repair(infile, outfile);
61+
else if(xml)
62+
xml_repair(infile, outfile);
63+
else assert(false);
64+
65+
infile.close();
66+
outfile.close();
67+
68+
return 0;
69+
}
70+
71+
/*******************************************************************\
72+
73+
Function: main
74+
75+
Inputs:
76+
77+
Outputs:
78+
79+
Purpose:
80+
81+
\*******************************************************************/
82+
83+
#ifdef _MSC_VER
84+
int wmain(int argc, const wchar_t **argv_wide)
85+
{
86+
const char **argv=narrow_argv(argc, argv_wide);
87+
if(argc!=4)
88+
{
89+
std::cerr << "Usage: output-repair.exe "
90+
<< "(--json | --xml) <infile> outfile>\n\n";
91+
return -1;
92+
}
93+
return repair(argv);
94+
}
95+
#else
96+
int main(int argc, const char **argv)
97+
{
98+
if(argc!=4)
99+
{
100+
std::cerr << "Usage: output-repair "
101+
<< "(--json | --xml) <infile> <outfile>\n\n";
102+
return -1;
103+
}
104+
return repair(argv);
105+
}
106+
#endif

src/output-repair/xml_repair.cpp

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*******************************************************************\
2+
3+
Module: XML repair tool
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
#include <util/unicode.h>
10+
11+
#include <fstream>
12+
#include <iostream>
13+
#include <stack>
14+
#include <sstream>
15+
16+
#include "xml_repair.h"
17+
18+
// cut non-closed branches at this level
19+
#define BACKTRACK_LEVEL 1
20+
21+
/*******************************************************************\
22+
23+
Function: xml_repair
24+
25+
Inputs:
26+
27+
Outputs:
28+
29+
Purpose:
30+
31+
\*******************************************************************/
32+
33+
void xml_repair(std::ifstream &infile, std::ofstream &outfile)
34+
{
35+
std::stack<std::string> tags; // tag stack
36+
bool intag=false; // within a tag
37+
bool intagname=false; // within a tag name
38+
bool closingtag=false; // it's a closing tag
39+
std::stringstream tag; // the tag name
40+
std::stringstream backtrackbuffer; // buffer for cutting branches
41+
char c, lastc=' '; // current and last character
42+
43+
while(infile >> std::noskipws >> c)
44+
{
45+
backtrackbuffer << c;
46+
switch(c)
47+
{
48+
case '<' : intag=intagname=true; break;
49+
case ' ' :
50+
if(intag)
51+
intagname=false;
52+
break;
53+
case '/' :
54+
if(intag)
55+
{
56+
if(lastc=='<')
57+
closingtag=true;
58+
else
59+
intagname=false;
60+
}
61+
break;
62+
case '>' :
63+
if(!closingtag && lastc!='/') // end of opening tag
64+
{
65+
if(lastc!='?')
66+
{
67+
tags.push(tag.str());
68+
}
69+
}
70+
else // end of closing tag
71+
{
72+
if(lastc!='/')
73+
{
74+
tags.pop();
75+
}
76+
}
77+
// clear tag name buffer
78+
tag.seekp(0);
79+
tag.seekg(0);
80+
tag.str("");
81+
tag.clear();
82+
83+
if(tags.size()<=BACKTRACK_LEVEL)
84+
{
85+
// at this level everything in the buffer is part of the output
86+
outfile << backtrackbuffer.str();
87+
88+
// clear buffer
89+
backtrackbuffer.seekp(0);
90+
backtrackbuffer.seekg(0);
91+
backtrackbuffer.str("");
92+
backtrackbuffer.clear();
93+
}
94+
intag=intagname=closingtag=false;
95+
break;
96+
default :
97+
if(intagname)
98+
tag << c;
99+
break;
100+
}
101+
lastc=c;
102+
}
103+
if(tags.size()>0) // truncated
104+
{
105+
// everything above BACKTRACK_LEVEL is discarded
106+
// now, add missing closing tags below it:
107+
while(!tags.empty())
108+
{
109+
if(tags.size()<=BACKTRACK_LEVEL)
110+
{
111+
outfile << std::endl << "</" << tags.top() << ">" << std::endl;
112+
}
113+
tags.pop();
114+
}
115+
}
116+
}

src/output-repair/xml_repair.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*******************************************************************\
2+
3+
Module: XML repair tool
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_OUTPUT_REPAIR_XML_REPAIR_H
10+
#define CPROVER_OUTPUT_REPAIR_XML_REPAIR_H
11+
12+
#include <fstream>
13+
14+
void xml_repair(std::ifstream &infile, std::ofstream &outfile);
15+
16+
#endif // CPROVER_OUTPUT_REPAIR_XML_REPAIR_H

0 commit comments

Comments
 (0)