mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
gdbus-codegen: Error on invalid dbus types
Introduce slightly modified (dbus specific) versions of variant_is_signature and variant_type_string_scan in order to fail early on bad type strings.
This commit is contained in:
parent
4aa63defdf
commit
a1a00a3071
@ -23,6 +23,69 @@ from . import utils
|
|||||||
from .utils import print_error
|
from .utils import print_error
|
||||||
|
|
||||||
|
|
||||||
|
# See: variant_type_string_scan_internal()
|
||||||
|
def variant_type_string_scan(signature: str, depth_limit: int, i=0):
|
||||||
|
beg_char = signature[i]
|
||||||
|
i += 1
|
||||||
|
if beg_char == "(":
|
||||||
|
while signature[i] != ")":
|
||||||
|
if depth_limit == 0:
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". Too much recursion beginning at {i}.'
|
||||||
|
)
|
||||||
|
i = variant_type_string_scan(signature, depth_limit - 1, i)
|
||||||
|
i += 1
|
||||||
|
elif beg_char == "{":
|
||||||
|
if depth_limit == 0:
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". Too much recursion beginning at {i}.'
|
||||||
|
)
|
||||||
|
elif signature[i] not in "bynqihuxtdsog?":
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". "{signature[i]}" is not a valid type for dictionary keys at position {i}.'
|
||||||
|
)
|
||||||
|
i += 1
|
||||||
|
i = variant_type_string_scan(signature, depth_limit - 1, i)
|
||||||
|
if signature[i] != "}":
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". Dict must end with "}}" at position {i}.'
|
||||||
|
)
|
||||||
|
i += 1
|
||||||
|
elif beg_char == "a":
|
||||||
|
if depth_limit == 0:
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". Too much recursion beginning at {i}.'
|
||||||
|
)
|
||||||
|
i = variant_type_string_scan(signature, depth_limit - 1, i)
|
||||||
|
elif beg_char not in "bynqiuxtdsogvr*?h":
|
||||||
|
raise ValueError(
|
||||||
|
f'Bad signature "{signature}". Unexpected value "{beg_char}" at position {i}.'
|
||||||
|
)
|
||||||
|
return i
|
||||||
|
|
||||||
|
|
||||||
|
# variant_check_signature() does not perform a strict validation check and
|
||||||
|
# should not be used in security sensitive contexts.
|
||||||
|
def variant_check_signature(signature: str):
|
||||||
|
# See: gvariant-internal.h
|
||||||
|
G_VARIANT_MAX_RECURSION_DEPTH = 128
|
||||||
|
if len(signature) > 255:
|
||||||
|
print_error("D-Bus maximum signature length of 255 exceeded.")
|
||||||
|
for s in signature:
|
||||||
|
if s not in "ybnqiuxthdvasog(){}":
|
||||||
|
print_error(
|
||||||
|
f'Bad signature "{signature}". "{s}" is not a valid D-Bus type.'
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
variant_type_string_scan(signature, G_VARIANT_MAX_RECURSION_DEPTH)
|
||||||
|
except IndexError:
|
||||||
|
print_error(
|
||||||
|
f'Bad signature "{signature}". Error parsing string or brackets not closed.'
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
print_error(e.args[0])
|
||||||
|
|
||||||
|
|
||||||
class Annotation:
|
class Annotation:
|
||||||
def __init__(self, key, value):
|
def __init__(self, key, value):
|
||||||
self.key = key
|
self.key = key
|
||||||
@ -88,6 +151,7 @@ class Arg:
|
|||||||
self.gvalue_set = "g_value_take_variant"
|
self.gvalue_set = "g_value_take_variant"
|
||||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__VARIANT"
|
self.gclosure_marshaller = "g_cclosure_marshal_VOID__VARIANT"
|
||||||
self.array_annotation = ""
|
self.array_annotation = ""
|
||||||
|
variant_check_signature(self.signature)
|
||||||
|
|
||||||
if not utils.lookup_annotation(
|
if not utils.lookup_annotation(
|
||||||
self.annotations, "org.gtk.GDBus.C.ForceGVariant"
|
self.annotations, "org.gtk.GDBus.C.ForceGVariant"
|
||||||
|
@ -627,6 +627,64 @@ G_END_DECLS
|
|||||||
"2.64",
|
"2.64",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
||||||
|
def test_dbus_types(self):
|
||||||
|
bad_types = [
|
||||||
|
"{vs}", # Bad dictionary key type
|
||||||
|
"(ss(s{{sv}s}))", # Bad dictionary key types
|
||||||
|
"{s", # Unterminated dictionary
|
||||||
|
"(s{sss})", # Unterminated dictionary
|
||||||
|
"z", # Bad type
|
||||||
|
"(ssms)", # Bad type
|
||||||
|
"(", # Unterminated tuple
|
||||||
|
"(((ss))", # Unterminated tuple
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", # Too much recursion
|
||||||
|
"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((("
|
||||||
|
"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((s))"
|
||||||
|
"))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"
|
||||||
|
"))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))", # Too much recursion
|
||||||
|
"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{"
|
||||||
|
"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{sv}"
|
||||||
|
"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}"
|
||||||
|
"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}", # Too much recursion
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaa{sv})", # Too much recursion
|
||||||
|
"(ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
|
||||||
|
"ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
|
||||||
|
"ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
|
||||||
|
"ssssssssssssssssssssssssssssssssssssssssssssssssssssssssss)", # Too long
|
||||||
|
]
|
||||||
|
for t in bad_types:
|
||||||
|
interface_xml = f"""
|
||||||
|
<node>
|
||||||
|
<interface name="BadTypes">
|
||||||
|
<property type="{t}" name="BadPropertyType" access="read" />
|
||||||
|
</interface>
|
||||||
|
</node>"""
|
||||||
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
|
self.runCodegenWithInterface(
|
||||||
|
interface_xml, "--output", "/dev/stdout", "--body"
|
||||||
|
)
|
||||||
|
good_types = [
|
||||||
|
"si{s{b(ybnqiuxtdh)}}{yv}{nv}{dv}",
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", # 128 Levels of recursion
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa{sv})", # 128 Levels of recursion
|
||||||
|
]
|
||||||
|
for t in good_types:
|
||||||
|
interface_xml = f"""
|
||||||
|
<node>
|
||||||
|
<interface name="GoodTypes">
|
||||||
|
<property type="{t}" name="GoodPropertyType" access="read" />
|
||||||
|
</interface>
|
||||||
|
</node>"""
|
||||||
|
result = self.runCodegenWithInterface(
|
||||||
|
interface_xml, "--output", "/dev/stdout", "--body"
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
|
||||||
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
||||||
def test_unix_fd_types_and_annotations(self):
|
def test_unix_fd_types_and_annotations(self):
|
||||||
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.
|
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.
|
||||||
|
Loading…
Reference in New Issue
Block a user