Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ruby / Yukihiro Matsumoto_Programming Ruby.doc
Скачиваний:
122
Добавлен:
06.06.2015
Размер:
2.71 Mб
Скачать

Freezing Objects

There are times when you've worked hard to make your object exactly right, and you'll be damned if you'll let anyone just change it. Perhaps you need to pass some kind of opaque object between two of your classes via some third-party object, and you want to make sure it arrives unmodified. Perhaps you want to use an object as a hash key, and need to make sure that no one modifies it while it's being used. Perhaps something is corrupting one of your objects, and you'd like Ruby to raise an exception as soon as the change occurs.

Ruby provides a very simple mechanism to help with this. Any object can be frozenby invokingObject#freeze . A frozen object may not be modified: you can't change its instance variables (directly or indirectly), you can't associate singleton methods with it, and, if it is a class or module, you can't add, delete, or modify its methods. Once frozen, an object stays frozen: there is noObject#thaw . You can test to see if an object is frozen usingObject#frozen? .

What happens when you copy a frozen object? That depends on the method you use. If you call an object's clonemethod, the entire object state (including whether it is frozen) is copied to the new object. On the other hand,duptypically copies only the object's contents---the new copy will not inherit the frozen status.

str1 = "hello"

str1.freeze

»

"hello"

str1.frozen?

»

true

str2 = str1.clone

str2.frozen?

»

true

str3 = str1.dup

str3.frozen?

»

false

Although freezing objects may initially seem like a good idea, you might want to hold off doing it until you come across a real need. Freezing is one of those ideas that looks essential on paper but isn't used much in practice.

Locking Ruby in the Safe

Walter Webcoder has a great idea for a portal site: The Web Arithmetic Page. Surrounded by all sorts of cool mathematical links and banner ads that will make him rich is a simple central frame, containing a text field and a button. Users type an arithmetic expression into the field, press the button, and the answer is displayed. All the world's calculators become obsolete overnight, and Walter cashes in and retires to devote his life to his collection of car license plate numbers.

Implementing the calculator is easy, thinks Walter. He accesses the contents of the form field using Ruby's CGI library, and uses the evalmethod to evaluate the string as an expression.

require 'cgi'

cgi = CGI::new("html4")

# Fetch the value of the form field "expression"

expr = cgi["expression"].to_s

begin

  result = eval(expr)

rescue Exception => detail

  # handle bad expressions

end

# display result back to user...

Roughly seven seconds after Walter puts the application online, a twelve-year-old from Waxahachie with glandular problems and no real life types ``system("rm *")'' into the form and, like his application, Walter's dreams come tumbling down.

Walter learned an important lesson: All external data is dangerous. Don't let it close to interfaces that can modify your system.In this case, the content of the form field was the external data, and the call toevalwas the security breach.

Fortunately, Ruby provides support for reducing this risk. All information from the outside world can be marked as tainted. When running in a safe mode, potentially dangerous methods will raise aSecurityErrorif passed a tainted object.

Соседние файлы в папке Ruby