ruby-changes:67773
From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Fri, 10 Sep 2021 20:01:51 +0900 (JST)
Subject: [ruby-changes:67773] 72a43d4a4b (master): include/ruby/internal/intern/marshal.h: add doxygen
https://git.ruby-lang.org/ruby.git/commit/?id=72a43d4a4b From 72a43d4a4b6d4d41d15578b465bb393f6ed051ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?= <shyouhei@r...> Date: Mon, 15 Mar 2021 10:04:43 +0900 Subject: include/ruby/internal/intern/marshal.h: add doxygen Must not be a bad idea to improve documents. [ci skip] --- include/ruby/internal/intern/marshal.h | 81 +++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/include/ruby/internal/intern/marshal.h b/include/ruby/internal/intern/marshal.h index 1da025b..118d78a 100644 --- a/include/ruby/internal/intern/marshal.h +++ b/include/ruby/internal/intern/marshal.h @@ -26,8 +26,85 @@ https://github.com/ruby/ruby/blob/trunk/include/ruby/internal/intern/marshal.h#L26 RBIMPL_SYMBOL_EXPORT_BEGIN() /* marshal.c */ -VALUE rb_marshal_dump(VALUE, VALUE); -VALUE rb_marshal_load(VALUE); + +/** + * Serialises the given object and all its referring objects, to write them + * down to the passed port. + * + * @param[in] obj Target object to dump. + * @param[out] port IO-like destination buffer. + * @exception rb_eTypeError `obj` cannot be dumped for some reason. + * @exception rb_eRuntimeError `obj` was tampered during dumping. + * @exception rb_eArgError Traversal too deep. + * @return The passed `port` as-is. + * @post Serialised representation of `obj` is written to `port`. + * @note `port` is basically an IO but StringIO is also possible. + */ +VALUE rb_marshal_dump(VALUE obj, VALUE port); + +/** + * Deserialises a previous output of rb_marshal_dump() into a network of + * objects. + * + * @param[in,out] port Either IO or String. + * @exception rb_eTypeError `port` is in unexpected type. + * @exception rb_eArgError Contents of `port` is broken. + * @return Object(s) rebuilt using the info from `port`. + * + * SECURITY CONSIDERATIONS + * ======================== + * + * @warning By design, rb_marshal_load() can deserialise almost any + * class loaded into the Ruby process. In many cases this can + * lead to remote code execution if the Marshal data is loaded + * from an untrusted source. + * @warning As a result, rb_marshal_load() is not suitable as a general + * purpose serialisation format and you should never unmarshal + * user supplied input or other untrusted data. + * @warning If you need to deserialise untrusted data, use JSON or + * another serialisation format that is only able to load + * simple, 'primitive' types such as String, Array, Hash, etc. + * Never allow user input to specify arbitrary types to + * deserialise into. + */ +VALUE rb_marshal_load(VALUE port); + +/** + * Marshal format compatibility layer. Over time, classes evolve, so that + * their internal data structure change drastically. For instance an instance + * of ::rb_cRange was made of ::RUBY_T_OBJECT in 1.x., but in 3.x it is a + * ::RUBY_T_STRUCT now. In order to keep binary compatibility, we "fake" the + * marshalled representation to stick to old types. This is the API to enable + * that manoeuvre. Here is how: + * + * First, because you are going to keep backwards compatibility, you need to + * retain the old implementation of your class. Rename it, and keep the class + * somewhere (for instance rb_register_global_address() could help). Next + * create your new class. Do whatever you want. + * + * Then, this is the key point. Create two new "bridge" functions that convert + * the structs back and forth: + * + * - the "dumper" function that takes an instance of the new class, and + * returns an instance of the old one. This is called from + * rb_marshal_dump(), to keep it possible for old programs to read your new + * data. + * + * - the "loader" function that takes two arguments, new one and old one, in + * that order. rb_marshal_load() calls this function when it finds a + * representation of the retained old class. The old one passed to this + * function is the reconstructed instance of the old class. + * Reverse-engineer that to modify the new one, to have the identical + * contents. + * + * Finally, connect all of them using this function. + * + * @param[in] newclass The class that needs conversion. + * @param[in] oldclass Old implementation of `newclass`. + * @param[in] dumper Function that converts `newclass` to `oldclass`. + * @param[in] loader Function that converts `oldclass` to `newclass`. + * @exception rb_eTypeError `newclass` has no allocator. + */ void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); RBIMPL_SYMBOL_EXPORT_END() -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/