Ruby: include/ruby/internal/intern/marshal.h File Reference

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

Functions
marshal.h File Reference

Public APIs related to rb_mMarshal. More...

`#include "ruby/internal/dllexport.h"`
`#include "ruby/internal/value.h"`

Go to the source code of this file.

## Functions
VALUE | rb_marshal_dump (VALUE obj, VALUE port)
| Serialises the given object and all its referring objects, to write them down to the passed port.
VALUE | rb_marshal_load (VALUE port)
| Deserialises a previous output of rb_marshal_dump() into a network of objects.
void | rb_marshal_define_compat (VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
| Marshal format compatibility layer.

## Detailed Description

Public APIs related to rb_mMarshal.

Author
  Ruby developers ruby-.nosp@m.core.nosp@m.@ruby.nosp@m.-lan.nosp@m.g.org

Copyright
  This file is a part of the programming language Ruby. Permission is hereby granted, to either redistribute and/or modify this file, provided that the conditions mentioned in the file COPYING are met. Consult the file for details.

Warning
  Symbols prefixed with either `RBIMPL` or `rbimpl` are implementation details. Don't take them as canon. They could rapidly appear then vanish. The name (path) of this header file is also an implementation detail. Do not expect it to persist at the place it is now. Developers are free to move it anywhere anytime at will.

Note
  To ruby-core: remember that this header can be possibly recursively included from extension libraries written in C++. Do not expect for instance `__VA_ARGS__` is always available. We assume C99 for ruby itself but we don't assume languages of extension libraries. They could be written in C++98.

Definition in file marshal.h.

## Function Documentation

## ◆ rb_marshal_define_compat()

void rb_marshal_define_compat | ( | VALUE | newclass,
|  | VALUE | oldclass,
|  | VALUE(* | dumper )(VALUE),
|  | VALUE(* | loader )(VALUE, VALUE) )

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.

Parameters

  [in] | newclass | The class that needs conversion.
  [in] | oldclass | Old implementation of `newclass`.
  [in] | dumper | Function that converts `newclass` to `oldclass`.
  [in] | loader | Function that converts `oldclass` to `newclass`.

Exceptions

  rb_eTypeError | `newclass` has no allocator.

Definition at line 150 of file marshal.c.

## ◆ rb_marshal_dump()

VALUE rb_marshal_dump | ( | VALUE | obj,
|  | VALUE | port )

Serialises the given object and all its referring objects, to write them down to the passed port.

Parameters

  [in] | obj | Target object to dump.
  [out] | port | IO-like destination buffer.

Exceptions

  rb_eTypeError | `obj` cannot be dumped for some reason.
  rb_eRuntimeError | `obj` was tampered during dumping.
  rb_eArgError | Traversal too deep.

Returns
  The passed `port` as-is.

Postcondition
  Serialised representation of `obj` is written to `port`.

Note
  `port` is basically an IO but StringIO is also possible.

Definition at line 2533 of file marshal.c.

## ◆ rb_marshal_load()

VALUE rb_marshal_load | ( | VALUE | port | ) |

Deserialises a previous output of rb_marshal_dump() into a network of objects.

Parameters

  [in,out] | port | Either IO or String.

Exceptions

  rb_eTypeError | `port` is in unexpected type.
  rb_eArgError | Contents of `port` is broken.

Returns
  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.
  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.
  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.

Definition at line 2539 of file marshal.c.