tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

JSString.py (3475B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 # You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 # Pretty-printers for SpiderMonkey strings.
      6 
      7 import gdb
      8 
      9 import mozilla.prettyprinters
     10 from mozilla.CellHeader import get_header_length_and_flags
     11 from mozilla.prettyprinters import ptr_pretty_printer
     12 
     13 try:
     14    chr(10000)  # UPPER RIGHT PENCIL
     15 except ValueError:  # yuck, we are in Python 2.x, so chr() is 8-bit
     16    chr = unichr  # replace with teh unicodes
     17 
     18 # Forget any printers from previous loads of this module.
     19 mozilla.prettyprinters.clear_module_printers(__name__)
     20 
     21 
     22 class JSStringTypeCache:
     23    # Cache information about the JSString type for this objfile.
     24    def __init__(self, cache):
     25        dummy = gdb.Value(0).cast(cache.JSString_ptr_t)
     26        self.ATOM_BIT = dummy["ATOM_BIT"]
     27        self.LINEAR_BIT = dummy["LINEAR_BIT"]
     28        self.INLINE_CHARS_BIT = dummy["INLINE_CHARS_BIT"]
     29        self.TYPE_FLAGS_MASK = dummy["TYPE_FLAGS_MASK"]
     30        self.LATIN1_CHARS_BIT = dummy["LATIN1_CHARS_BIT"]
     31 
     32 
     33 class Common(mozilla.prettyprinters.Pointer):
     34    def __init__(self, value, cache):
     35        super().__init__(value, cache)
     36        if not cache.mod_JSString:
     37            cache.mod_JSString = JSStringTypeCache(cache)
     38        self.stc = cache.mod_JSString
     39 
     40 
     41 @ptr_pretty_printer("JSString")
     42 class JSStringPtr(Common):
     43    def display_hint(self):
     44        return "string"
     45 
     46    def chars(self):
     47        d = self.value["d"]
     48        length, flags = get_header_length_and_flags(self.value, self.cache)
     49 
     50        corrupt = {
     51            0x2F2F2F2F: "JS_FRESH_NURSERY_PATTERN",
     52            0x2B2B2B2B: "JS_SWEPT_NURSERY_PATTERN",
     53            0xE5E5E5E5: "jemalloc freed memory",
     54        }.get(flags & 0xFFFFFFFF)
     55        if corrupt:
     56            yield from "<CORRUPT:%s>" % corrupt
     57            return
     58        is_rope = (flags & self.stc.LINEAR_BIT) == 0
     59        if is_rope:
     60            for c in JSStringPtr(d["s"]["u2"]["left"], self.cache).chars():
     61                yield c
     62            for c in JSStringPtr(d["s"]["u3"]["right"], self.cache).chars():
     63                yield c
     64        else:
     65            is_inline = (flags & self.stc.INLINE_CHARS_BIT) != 0
     66            is_latin1 = (flags & self.stc.LATIN1_CHARS_BIT) != 0
     67            if is_inline:
     68                if is_latin1:
     69                    chars = d["inlineStorageLatin1"]
     70                else:
     71                    chars = d["inlineStorageTwoByte"]
     72            elif is_latin1:
     73                chars = d["s"]["u2"]["nonInlineCharsLatin1"]
     74            else:
     75                chars = d["s"]["u2"]["nonInlineCharsTwoByte"]
     76            for i in range(int(length)):
     77                yield chars[i]
     78 
     79    def to_string(self, maxlen=200):
     80        s = ""
     81        invalid_chars_allowed = 2
     82        for c in self.chars():
     83            if len(s) >= maxlen:
     84                s += "..."
     85                break
     86 
     87            try:
     88                # Convert from gdb.Value to string.
     89                s += chr(c)
     90            except ValueError:
     91                if invalid_chars_allowed == 0:
     92                    s += "<TOO_MANY_INVALID_CHARS>"
     93                    break
     94                else:
     95                    invalid_chars_allowed -= 1
     96                    s += "\\x%04x" % (c & 0xFFFF)
     97        return s
     98 
     99 
    100 @ptr_pretty_printer("JSAtom")
    101 class JSAtomPtr(Common):
    102    def to_string(self):
    103        return self.value.cast(self.cache.JSString_ptr_t)