From: =?utf-8?q?Timo_R=C3=B6hling?= <roehling@debian.org>
Date: Wed, 17 Sep 2025 15:15:33 +0200
Subject: Use safe loader for YAML input

Origin: upstream, https://github.com/ros/dynamic_reconfigure/pull/205
Bug: https://github.com/ros/dynamic_reconfigure/issues/202
---
 scripts/dynparam | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/scripts/dynparam b/scripts/dynparam
index aa77b22..50ba6b8 100755
--- a/scripts/dynparam
+++ b/scripts/dynparam
@@ -41,6 +41,28 @@ import optparse
 import sys
 import yaml
 import dynamic_reconfigure.client
+import dynamic_reconfigure.encoding
+
+
+class CustomLoader(yaml.SafeLoader):
+    pass
+
+
+class CustomDumper(yaml.SafeDumper):
+    pass
+
+
+def config_constructor(loader, node):
+    return loader.construct_yaml_map(node)
+
+
+def config_representer(dumper, data):
+    return dumper.represent_mapping('!dynamic_reconfigure.encoding.Config', data)
+
+
+CustomLoader.add_constructor('!dynamic_reconfigure.encoding.Config', config_constructor)
+CustomDumper.add_representer(dynamic_reconfigure.encoding.Config, config_representer)
+
 
 def do_list():
     connect()
@@ -109,7 +131,7 @@ Examples:
     node = args[0]
     if len(args) == 2:
         node, value = args[0], args[1]
-        values_dict = yaml.load(value, Loader=yaml.Loader)
+        values_dict = yaml.load(value, Loader=CustomLoader)
         if type(values_dict) != dict:
             parser.error('invalid arguments. Please specify either a node name, parameter name and parameter value, or a node name and a YAML dictionary')
     elif len(args) == 3:
@@ -158,7 +180,7 @@ def do_load():
     f = open(path, 'r')
     try:
         params = {}
-        for doc in yaml.load_all(f.read(), Loader=yaml.Loader):
+        for doc in yaml.load_all(f.read(), Loader=CustomLoader):
             params.update(doc)
     finally:
         f.close()
@@ -185,7 +207,7 @@ def do_dump():
     if params is not None:
         f = open(path, 'w')
         try:
-            yaml.dump(params, f)
+            yaml.dump(params, f, Dumper=CustomDumper)
             return
         finally:
             f.close()
