fix: truncate large strings in fuchsia

This commit is contained in:
Simon Cruanes 2024-02-20 15:10:20 -05:00
parent a1df7eb88e
commit 05be245163
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
2 changed files with 52 additions and 38 deletions

View file

@ -29,27 +29,42 @@ module I64 = struct
let ( asr ) = shift_right let ( asr ) = shift_right
end end
open struct
(** maximum length as specified in the
{{: https://fuchsia.dev/fuchsia-src/reference/tracing/trace-format} spec} *)
let max_str_len = 32000
(** Length of string, in words *)
let[@inline] str_len_word (s : string) =
let len = String.length s in
assert (len <= max_str_len);
round_to_word len lsr 3
let str_len_word_maybe_too_big s =
let len = min max_str_len (String.length s) in
round_to_word len lsr 3
end
module Str_ref = struct module Str_ref = struct
type t = int type t = int
(** 16 bits *) (** 16 bits *)
let[@inline never] inline_fail_ () =
invalid_arg
(Printf.sprintf "fuchsia: max length of strings is %d" max_str_len)
let inline (size : int) : t = let inline (size : int) : t =
if size > 32_000 then invalid_arg "fuchsia: max length of strings is 20_000"; if size > max_str_len then
if size = 0 then inline_fail_ ()
else if size = 0 then
0 0
else else
(1 lsl 15) lor size (1 lsl 15) lor size
end end
open struct
(** maximum length as specified in the
{{: https://fuchsia.dev/fuchsia-src/reference/tracing/trace-format} spec} *)
let max_str_len = 32000
end
(** [truncate_string s] truncates [s] to the maximum length allowed for (** [truncate_string s] truncates [s] to the maximum length allowed for
strings. If [s] is already short enough, no allocation is done. *) strings. If [s] is already short enough, no allocation is done. *)
let truncate_string s : string = let[@inline] truncate_string s : string =
if String.length s <= max_str_len then if String.length s <= max_str_len then
s s
else else
@ -108,9 +123,10 @@ module Metadata = struct
end end
module Provider_info = struct module Provider_info = struct
let size_word ~name () = 1 + (round_to_word (String.length name) lsr 3) let size_word ~name () = 1 + str_len_word name
let encode (out : Output.t) ~(id : int) ~name () : unit = let encode (out : Output.t) ~(id : int) ~name () : unit =
let name = truncate_string name in
let size = size_word ~name () in let size = size_word ~name () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
let hd = let hd =
@ -118,7 +134,7 @@ module Metadata = struct
(of_int size lsl 4) (of_int size lsl 4)
lor (1L lsl 16) lor (1L lsl 16)
lor (of_int id lsl 20) lor (of_int id lsl 20)
lor (of_int (Str_ref.inline (String.length name)) lsl 52)) lor (of_int (Str_ref.inline (str_len_word name)) lsl 52))
in in
Buf.add_i64 buf hd; Buf.add_i64 buf hd;
Buf.add_string buf name Buf.add_string buf name
@ -140,15 +156,12 @@ module Argument = struct
let size_word (self : _ t) = let size_word (self : _ t) =
let name, data = self in let name, data = self in
match data with match data with
| `None | `Bool _ -> 1 + (round_to_word (String.length name) lsr 3) | `None | `Bool _ -> 1 + str_len_word name
| `Int i when is_i32_ i -> 1 + (round_to_word (String.length name) lsr 3) | `Int i when is_i32_ i -> 1 + str_len_word name
| `Int _ -> (* int64 *) 2 + (round_to_word (String.length name) lsr 3) | `Int _ -> (* int64 *) 2 + str_len_word name
| `Float _ -> 2 + (round_to_word (String.length name) lsr 3) | `Float _ -> 2 + str_len_word name
| `String s -> | `String s -> 1 + str_len_word_maybe_too_big s + str_len_word name
1 | `Kid _ -> 2 + str_len_word name
+ (round_to_word (String.length s) lsr 3)
+ (round_to_word (String.length name) lsr 3)
| `Kid _ -> 2 + (round_to_word (String.length name) lsr 3)
open struct open struct
external int_of_bool : bool -> int = "%identity" external int_of_bool : bool -> int = "%identity"
@ -156,6 +169,7 @@ module Argument = struct
let encode (buf : Buf.t) (self : _ t) : unit = let encode (buf : Buf.t) (self : _ t) : unit =
let name, data = self in let name, data = self in
let name = truncate_string name in
let size = size_word self in let size = size_word self in
(* part of header with argument name + size *) (* part of header with argument name + size *)
@ -186,6 +200,7 @@ module Argument = struct
Buf.add_string buf name; Buf.add_string buf name;
Buf.add_i64 buf (I64.bits_of_float f) Buf.add_i64 buf (I64.bits_of_float f)
| `String s -> | `String s ->
let s = truncate_string s in
let hd = let hd =
I64.( I64.(
6L lor hd_arg_size 6L lor hd_arg_size
@ -271,12 +286,12 @@ module Event = struct
(** type=0 *) (** type=0 *)
module Instant = struct module Instant = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) / 8)
+ Arguments.size_word args + Arguments.size_word args
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args () let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args ()
: unit = : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -306,12 +321,12 @@ module Event = struct
(** type=1 *) (** type=1 *)
module Counter = struct module Counter = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + 1 (* counter id *) + Arguments.size_word args + 1 (* counter id *)
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args () let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args ()
: unit = : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -343,12 +358,12 @@ module Event = struct
(** type=2 *) (** type=2 *)
module Duration_begin = struct module Duration_begin = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + Arguments.size_word args
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args () let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args ()
: unit = : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -378,12 +393,12 @@ module Event = struct
(** type=3 *) (** type=3 *)
module Duration_end = struct module Duration_end = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + Arguments.size_word args
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args () let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns ~args ()
: unit = : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -413,12 +428,12 @@ module Event = struct
(** type=4 *) (** type=4 *)
module Duration_complete = struct module Duration_complete = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + 1 (* end timestamp *) + Arguments.size_word args + 1 (* end timestamp *)
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns
~end_time_ns ~args () : unit = ~end_time_ns ~args () : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -450,12 +465,12 @@ module Event = struct
(** type=5 *) (** type=5 *)
module Async_begin = struct module Async_begin = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + 1 (* async id *) + Arguments.size_word args + 1 (* async id *)
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns
~(async_id : int) ~args () : unit = ~(async_id : int) ~args () : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -486,12 +501,12 @@ module Event = struct
(** type=7 *) (** type=7 *)
module Async_end = struct module Async_end = struct
let size_word ~name ~t_ref ~args () : int = let size_word ~name ~t_ref ~args () : int =
1 + Thread_ref.size_word t_ref + 1 1 + Thread_ref.size_word t_ref + 1 (* timestamp *) + str_len_word name
(* timestamp *) + (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args + 1 (* async id *) + Arguments.size_word args + 1 (* async id *)
let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns let encode (out : Output.t) ~name ~(t_ref : Thread_ref.t) ~time_ns
~(async_id : int) ~args () : unit = ~(async_id : int) ~args () : unit =
let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in
@ -523,9 +538,7 @@ end
(** record type = 7 *) (** record type = 7 *)
module Kernel_object = struct module Kernel_object = struct
let size_word ~name ~args () : int = let size_word ~name ~args () : int =
1 + 1 1 + 1 + str_len_word name + Arguments.size_word args
+ (round_to_word (String.length name) lsr 3)
+ Arguments.size_word args
(* see: (* see:
https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/public/zircon/types.h;l=441?q=ZX_OBJ_TYPE&ss=fuchsia%2Ffuchsia https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/public/zircon/types.h;l=441?q=ZX_OBJ_TYPE&ss=fuchsia%2Ffuchsia
@ -537,6 +550,7 @@ module Kernel_object = struct
let ty_thread : ty = 2 let ty_thread : ty = 2
let encode (out : Output.t) ~name ~(ty : ty) ~(kid : int) ~args () : unit = let encode (out : Output.t) ~name ~(ty : ty) ~(kid : int) ~args () : unit =
let name = truncate_string name in
let size = size_word ~name ~args () in let size = size_word ~name ~args () in
let buf = Output.get_buf out ~available_word:size in let buf = Output.get_buf out ~available_word:size in

View file

@ -1,4 +1,4 @@
first trace first trace
100004467854160033000500000000000100000000000000560000000000000054001005000005804e61bc000000000068656c6c6f000000210001802a0000007800000000000000 100004467854160033000500000000000100000000000000560000000000000054001005000005804e61bc000000000068656c6c6f000000210001802a0000007800000000000000
second trace second trace
1000044678541600210000000000000000ca9a3b00000000330005000000000001000000000000005600000000000000300011000000b0006f63616d6c2d747261636500000000004400040500000580a0860100000000006f75746572000000404b4c0000000000440004050000058020bf020000000000696e6e657200000020aa440000000000540010050000058087d612000000000068656c6c6f000000210001802a0000007800000000000000 1000044678541600210000000000000000ca9a3b0000000033000500000000000100000000000000560000000000000030001100000020006f63616d6c2d747261636500000000004400040500000580a0860100000000006f75746572000000404b4c0000000000440004050000058020bf020000000000696e6e657200000020aa440000000000540010050000058087d612000000000068656c6c6f000000210001802a0000007800000000000000