Product SiteDocumentation Site

2.3. Symbols

Symbols in MRI Ruby are used for method, variable and constant lookup. They are implemented as integers so that they are faster to look up in hastables. Once symbol is created, memory allocated for it is never freed. This creates opportunity for attacker: if he is able to create arbitrary symbols, he could flood the application with unique symbols that will never be garbage collected. Memory consumption of Ruby process would only grow until it runs out of memory, resulting in Denial of Service attack.
Application developers should be careful when calling to_sym or intern on user-supplied strings. Additionally, other methods may convert supplied arguments to symbols internally, for example Object.send, Object.instance_variable_set, Object.instance_variable_get, Module.const_get or Module.const_set:
>> Symbol.all_symbols.size
=> 2956
>> Module.const_get('MY_SYMBOL')
NameError: uninitialized constant Module::MY_SYMBOL
>> Symbol.all_symbols.size
=> 2957
Array of all currently defined symbols is available through Symbol.all_symbols class method.
Starting from Ruby 2.0, method rb_check_id is available to Ruby C extensions, which returns 0 when String passed as argument is not already defined as Symbol. This makes overriding default intern methods possible.
SafeIntern gem makes use of rb_check_id and provides a patch for to_sym or intern methods of String. When the conversion from String to Symbol would define a new Symbol, either nil is returned or exception raised. Such approach prohibits creating any new Symbols other than those that are already defined by the application. In case the string is trusted, new symbol can be created by calling intern(:allow_unsafe).
Ruby 2.2 released 25th of Dec 2014 includes substantial improvements to it`s garbage collector, on of which is ability to garbage collect Symbols. This solves denial of service problems with Symbols present in previous versions of Ruby.