[m-rev.] diff: fix HTML character escapes in deep profiler
Julien Fischer
juliensf at cs.mu.OZ.AU
Wed Jun 22 17:21:29 AEST 2005
Estimated hours taken: 3
Branches: main, release
Workaround a problem where the deep profiling tool wasn't
escaping HTML special characters in procedure and file names.
deep_profiler/html_format.m:
deep_profiler/query.m:
When generating HTML make sure to escape special
characters, like '<', correctly.
Use state variable notation for the IO state
throughout these files.
Julien.
Index: html_format.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.5
diff -u -r1.5 html_format.m
--- html_format.m 25 Apr 2005 07:55:54 -0000 1.5
+++ html_format.m 21 Jun 2005 07:05:04 -0000
@@ -121,6 +121,11 @@
:- func deep_cmd_pref_to_url(preferences, deep, cmd) = string.
:- func plural(int) = string.
+
+ % Convert any special characters in a string into appropriate
+ % HTML escapes.
+ %
+:- func escape_html_string(string) = string.
%-----------------------------------------------------------------------------%
@@ -1840,18 +1845,18 @@
deep_lookup_proc_statics(Deep, PSPtr, PS),
ProcName = PS ^ ps_refined_id,
HTML = string__format("<A HREF=""%s"">%s</A>",
- [s(URL), s(ProcName)]).
+ [s(URL), s(escape_html_string(ProcName))]).
module_name_to_html_ref(Pref, Deep, ModuleName) = HTML :-
URL = deep_cmd_pref_to_url(Pref, Deep, module(ModuleName)),
HTML = string__format("<A HREF=""%s"">%s</A>",
- [s(URL), s(ModuleName)]).
+ [s(URL), s(escape_html_string(ModuleName))]).
clique_ptr_to_html_ref(Pref, Deep, ProcName, CliquePtr) = HTML :-
CliquePtr = clique_ptr(CliqueNum),
URL = deep_cmd_pref_to_url(Pref, Deep, clique(CliqueNum)),
HTML = string__format("<A HREF=""%s"">%s</A>",
- [s(URL), s(ProcName)]).
+ [s(URL), s(escape_html_string(ProcName))]).
deep_cmd_pref_to_url(Pref, Deep, Cmd) =
machine_datafile_cmd_pref_to_url(Deep ^ server_name,
@@ -1866,4 +1871,45 @@
Plural = "s"
).
+%-----------------------------------------------------------------------------%
+
+% This code was pretty much taken directly from extras/cgi/html.m.
+
+escape_html_string(String) = EscapedString :-
+ string.to_char_list(String, Chars),
+ escape_html_chars(Chars, EscapedChars, []),
+ string.from_char_list(EscapedChars, EscapedString).
+
+:- pred escape_html_chars(list(char)::in, list(char)::out, list(char)::in)
+ is det.
+
+escape_html_chars([]) --> [].
+escape_html_chars([Char | Chars]) -->
+ escape_html_char(Char),
+ escape_html_chars(Chars).
+
+:- pred escape_html_char(char::in, list(char)::out, list(char)::in) is det.
+
+escape_html_char(Char) -->
+ ( { special_html_char(Char, String) } ->
+ { string.to_char_list(String, Chars) },
+ insert(Chars)
+ ;
+ [Char]
+ ).
+
+:- pred special_html_char(char::in, string::out) is semidet.
+
+special_html_char('&', "&").
+special_html_char('<', "<").
+special_html_char('>', ">").
+
+:- pred insert(list(T), list(T), list(T)).
+:- mode insert(in, out, in) is det.
+
+insert(NewChars, Chars, Chars0) :-
+ list__append(NewChars, Chars0, Chars).
+
+%-----------------------------------------------------------------------------%
+:- end_module html_format.
%-----------------------------------------------------------------------------%
Index: query.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.6
diff -u -r1.6 query.m
--- query.m 24 Mar 2005 01:10:28 -0000 1.6
+++ query.m 22 Jun 2005 07:10:08 -0000
@@ -22,6 +22,7 @@
io::di, io::uo) is cc_multi.
%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
:- implementation.
@@ -46,8 +47,8 @@
%-----------------------------------------------------------------------------%
-try_exec(Cmd, Pref, Deep, HTML, IO0, IO) :-
- try_io(exec(Cmd, Pref, Deep), Result, IO0, IO),
+try_exec(Cmd, Pref, Deep, HTML, !IO) :-
+ try_io(exec(Cmd, Pref, Deep), Result, !IO),
(
Result = succeeded(HTML)
;
@@ -68,20 +69,20 @@
:- pred exec(cmd::in, preferences::in, deep::in, string::out,
io::di, io::uo) is det.
-exec(restart, _Pref, _Deep, _HTML, IO, IO) :-
+exec(restart, _Pref, _Deep, _HTML, !IO) :-
% Our caller is supposed to filter out restart commands.
error("exec: found restart command").
-exec(quit, _Pref, Deep, HTML, IO, IO) :-
+exec(quit, _Pref, Deep, HTML, !IO) :-
HTML = string__format(
"<H3>Shutting down deep profile server for %s.</H3>\n",
[s(Deep ^ data_file_name)]).
-exec(timeout(TimeOut), _Pref, _Deep, HTML, IO, IO) :-
+exec(timeout(TimeOut), _Pref, _Deep, HTML, !IO) :-
HTML = string__format("<H3>Timeout set to %d minutes</H3>\n",
[i(TimeOut)]).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = menu,
HTML = generate_menu_page(Cmd, Pref, Deep).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = root(MaybePercent),
deep_lookup_clique_index(Deep, Deep ^ root, RootCliquePtr),
RootCliquePtr = clique_ptr(RootCliqueNum),
@@ -94,7 +95,7 @@
generate_clique_page(Cmd, RootCliqueNum, Pref, Deep, HTML,
100, _)
).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = clique(CliqueNum),
CliquePtr = clique_ptr(CliqueNum),
( valid_clique_ptr(Deep, CliquePtr) ->
@@ -105,7 +106,7 @@
"There is no clique with that number.\n" ++
page_footer(Cmd, Pref, Deep)
).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = proc(PSI),
PSPtr = proc_static_ptr(PSI),
( valid_proc_static_ptr(Deep, PSPtr) ->
@@ -116,23 +117,22 @@
"There is no procedure with that number.\n" ++
page_footer(Cmd, Pref, Deep)
).
-exec(Cmd, Pref, Deep, HTML, IO0, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = proc_callers(PSI, CallerGroups, BunchNum),
PSPtr = proc_static_ptr(PSI),
( valid_proc_static_ptr(Deep, PSPtr) ->
generate_proc_callers_page(Cmd, PSPtr, CallerGroups, BunchNum,
- Pref, Deep, HTML, IO0, IO)
+ Pref, Deep, HTML, !IO)
;
HTML =
page_banner(Cmd, Pref) ++
"There is no procedure with that number.\n" ++
- page_footer(Cmd, Pref, Deep),
- IO = IO0
+ page_footer(Cmd, Pref, Deep)
).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = modules,
HTML = generate_modules_page(Cmd, Pref, Deep).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = module(ModuleName),
( map__search(Deep ^ module_data, ModuleName, ModuleData) ->
HTML = generate_module_page(Cmd, ModuleName, ModuleData,
@@ -143,19 +143,19 @@
"There is no procedure with that number.\n" ++
page_footer(Cmd, Pref, Deep)
).
-exec(Cmd, Pref, Deep, HTML, IO, IO) :-
+exec(Cmd, Pref, Deep, HTML, !IO) :-
Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
HTML = generate_top_procs_page(Cmd, Limit, CostKind, InclDesc, Scope,
Pref, Deep).
-exec(proc_static(PSI), _Pref, Deep, HTML, IO, IO) :-
+exec(proc_static(PSI), _Pref, Deep, HTML, !IO) :-
HTML = generate_proc_static_debug_page(PSI, Deep).
-exec(proc_dynamic(PDI), _Pref, Deep, HTML, IO, IO) :-
+exec(proc_dynamic(PDI), _Pref, Deep, HTML, !IO) :-
HTML = generate_proc_dynamic_debug_page(PDI, Deep).
-exec(call_site_static(CSSI), _Pref, Deep, HTML, IO, IO) :-
+exec(call_site_static(CSSI), _Pref, Deep, HTML, !IO) :-
HTML = generate_call_site_static_debug_page(CSSI, Deep).
-exec(call_site_dynamic(CSDI), _Pref, Deep, HTML, IO, IO) :-
+exec(call_site_dynamic(CSDI), _Pref, Deep, HTML, !IO) :-
HTML = generate_call_site_dynamic_debug_page(CSDI, Deep).
-exec(raw_clique(CI), _Pref, Deep, HTML, IO, IO) :-
+exec(raw_clique(CI), _Pref, Deep, HTML, !IO) :-
HTML = generate_clique_debug_page(CI, Deep).
%-----------------------------------------------------------------------------%
@@ -472,7 +472,7 @@
fields_header(Pref, source_proc, totals_meaningful,
wrap_clique_links(clique_ptr(CliqueNum),
Pref, Deep)) ++
- CliqueHTML ++
+ CliqueHTML ++
table_end(Pref) ++
page_footer(Cmd, Pref, Deep).
@@ -482,7 +482,7 @@
generate_proc_page(Cmd, PSPtr, Pref, Deep) =
page_banner(Cmd, Pref) ++
string__format("<H3>Summary of procedure %s:</H3>\n",
- [s(proc_static_name(Deep, PSPtr))]) ++
+ [s(escape_html_string(proc_static_name(Deep, PSPtr)))]) ++
table_start(Pref) ++
fields_header(Pref, source_proc, totals_meaningful,
wrap_proc_links(PSPtr, Pref, Deep)) ++
@@ -1049,7 +1049,11 @@
sum_line_group_measurements(SubLines, Own, Desc),
SummaryHTML =
string__format("<TD CLASS=id>%s:%d</TD>\n",
- [s(FileName), i(LineNumber)]) ++
+ [s(escape_html_string(FileName)), i(LineNumber)]) ++
+ %
+ % NOTE: we don't escape HTML special characters for
+ % 'CallSiteName' because it has already been done.
+ %
string__format("<TD CLASS=id>%s</TD>\n",
[s(CallSiteName)]),
(
@@ -1086,7 +1090,8 @@
FileName, LineNumber, Kind,
CallerPSPtr, CallSiteCallList)
),
- CSSContext = string__format("%s:%d", [s(FileName), i(LineNumber)]),
+ CSSContext = string__format("%s:%d",
+ [s(escape_html_string(FileName)), i(LineNumber)]),
LineGroup = add_context(CSSContext, LineGroup0).
:- func normal_call_site_summary_to_html(preferences, deep, string, int,
@@ -1134,6 +1139,10 @@
FileName, LineNumber, RawCallSiteName, CallerPSPtr),
CallSiteCallList),
sum_line_group_measurements(SubLines, Own, Desc),
+ %
+ % NOTE: we don't escape HTML special characters for
+ % 'CallSiteName' because it has already been done.
+ %
SummaryHTML =
string__format("<TD CLASS=id>%s</TD>\n",
[s(CallSiteName)]),
@@ -1256,11 +1265,12 @@
deep_lookup_csd_desc(Deep, CSDPtr, CallSiteDesc),
deep_lookup_clique_index(Deep, CalleePDPtr, CalleeCliquePtr),
call_site_dynamic_context(Deep, CSDPtr, FileName, LineNumber),
- Context = string__format("%s:%d", [s(FileName), i(LineNumber)]),
+ Context = string__format("%s:%d", [s(escape_html_string(FileName)),
+ i(LineNumber)]),
HTML = call_to_html(Pref, Deep, CallSiteDisplay, Context,
CallerPDPtr, CalleePDPtr,
MaybeCallerCliquePtr, CalleeCliquePtr),
- ProcName = proc_dynamic_name(Deep, CalleePDPtr),
+ ProcName = escape_html_string(proc_dynamic_name(Deep, CalleePDPtr)),
LineGroup = line_group(FileName, LineNumber, ProcName,
CallSiteOwn, CallSiteDesc, HTML, unit).
@@ -1354,7 +1364,7 @@
ChosenCliquePtr = clique_ptr(ChosenCliqueNum),
WrappedProcName = string__format("<A HREF=""%s"">%s</A>",
[s(deep_cmd_pref_to_url(Pref, Deep, clique(ChosenCliqueNum))),
- s(ProcName)]),
+ s(escape_html_string(ProcName))]),
(
CallSiteDisplay ^ display_wrap = always,
UsedProcName0 = WrappedProcName
@@ -1365,7 +1375,7 @@
( CallerCliquePtr \= CalleeCliquePtr ->
UsedProcName0 = WrappedProcName
;
- UsedProcName0 = ProcName
+ UsedProcName0 = escape_html_string(ProcName)
)
;
MaybeCallerCliquePtr = no,
@@ -1374,12 +1384,12 @@
UsedProcName0 = WrappedProcName
;
Assume = assume_within_clique,
- UsedProcName0 = ProcName
+ UsedProcName0 = escape_html_string(ProcName)
)
)
;
CallSiteDisplay ^ display_wrap = never,
- UsedProcName0 = ProcName
+ UsedProcName0 = escape_html_string(ProcName)
),
(
UsedProcName0 = WrappedProcName,
@@ -1387,7 +1397,7 @@
->
UsedProcName = UsedProcName0
;
- UsedProcName = ProcName
+ UsedProcName = escape_html_string(ProcName)
),
HTML =
string__format("<TD CLASS=id>%s</TD>\n", [s(Context)]) ++
@@ -1621,7 +1631,8 @@
Parent) = HTML :-
Cmd = proc(PSI),
WrappedProcName = string__format("<A HREF=""%s"">%s</A>",
- [s(deep_cmd_pref_to_url(Pref, Deep, Cmd)), s(ProcName)]),
+ [s(deep_cmd_pref_to_url(Pref, Deep, Cmd)),
+ s(escape_html_string(ProcName))]),
( NumLines = 0 ->
HTML = string__format("<H3>There are no %ss calling %s</H3>",
[s(Parent), s(WrappedProcName)])
@@ -1899,7 +1910,7 @@
Pref = Pref0 ^ pref_criteria := Criteria,
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)]).
+ [s(URL), s(escape_html_string(Str0))]).
:- func wrap_proc_links(proc_static_ptr, preferences, deep, string,
order_criteria) = string.
@@ -1910,7 +1921,7 @@
Pref = Pref0 ^ pref_criteria := Criteria,
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)]).
+ [s(URL), s(escape_html_string(Str0))]).
:- func wrap_proc_callers_links(proc_static_ptr, caller_groups, int,
preferences, deep, string, order_criteria) = string.
@@ -1922,7 +1933,7 @@
Pref = Pref0 ^ pref_criteria := Criteria,
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)]).
+ [s(URL), s(escape_html_string(Str0))]).
:- func wrap_module_links(string, preferences, deep, string,
order_criteria) = string.
@@ -1932,7 +1943,7 @@
Pref = Pref0 ^ pref_criteria := Criteria,
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)]).
+ [s(URL), s(escape_html_string(Str0))]).
:- func wrap_modules_links(preferences, deep, string, order_criteria) = string.
@@ -1941,7 +1952,7 @@
Pref = Pref0 ^ pref_criteria := Criteria,
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)]).
+ [s(URL), s(escape_html_string(Str0))]).
:- func wrap_top_procs_links(display_limit, preferences, deep, string,
order_criteria) = string.
@@ -1958,5 +1969,5 @@
Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
Str = string__format("<A HREF=%s>%s</A>",
- [s(URL), s(Str0)])
+ [s(URL), s(escape_html_string(Str0))])
).
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list