Deixando o interpretador Python maluco por diversão e lucro, ou Como se livrar de um colega de trabalho desenvolvedor Python

Você está lá, em apenas mais um dia comum de trabalho (ou diversão), debugando um sistema complexo e tentando entender porque diabos algo que deveria acontecer não acontece. Você consegue reduzir o seu problema a uma linha de código, que não se comporta como você espera:

>>> print 42 == 0
True

O resultado foi verdadeiro, ou seja, 42 realmente é igual a 0 no momento em que esta comparação roda! Mas como assim?! Em Python não é possível reabrir a classe dos números (int), reescrever os métodos de comparação para fazer isso dar certo.
Lembre-se que esta comparação estranha está no meio de um sistema complexo. Assim:

algo_que_deixa_interpretador_maluco()
print 42 == 0

Explicação: A função algo_que_deixa_interpretador_maluco está modificando o objeto “número inteiro 42” (mesmo os números são objetos). Mas os números são objetos imutáveis, como assim você modificou o valor de 42? Um número inteiro em Python (na verdade, CPython) é representado por uma struct do C, que entre outras coisas, contém um long do C com o mesmo valor  – o atributo ob_ival.

Simplificando uma longa história, quando temos uma comparação de números, ela é repassada para o nível do C, e os atributos ob_ival da struct C são comparados com o operador == do C. Basta então mudarmos o ob_ival do objeto “número 42” que podemos influenciar na comparação.

E para mudar o valor de ob_ival? Como é possível acessar e modificar o estado interno e a memória do interpretador? Com o módulo ctypes, da biblioteca padrão, podemos acessar do Python os tipos do C. Basta então conseguirmos achar na memória a struct do número 42. Mas isso é fácil, a função builtin id retorna exatamente o lugar na memória onde o objeto está. Com isso, temos tudo que precisamos.

import ctypes

if hasattr(ctypes.pythonapi, 'Py_InitModule4'):
    Py_ssize_t = ctypes.c_int
elif hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
    Py_ssize_t = ctypes.c_int64
else:
    raise TypeError("Cannot determine type of Py_ssize_t")

class PyObject(ctypes.Structure):
    pass # incomplete type

class PyObject(ctypes.Structure):
    _fields_ = [('ob_refcnt', Py_ssize_t),
                ('ob_type', ctypes.POINTER(PyObject))]

class PyIntObject(PyObject):
    _fields_ = [('ob_ival', ctypes.c_long)]

forty_two_object = PyIntObject.from_address(id(42))
forty_two_object.ob_ival = 0

print 42 == 0

Neste código, estamos primeiro conseguindo o endereço do objeto 42 (linha 20), depois criando a struct do ctypes (ponte entre o Python e a struct C), depois alteramos o ob_ival do 42 para 0, na memória do interpretador (linha 21).

A partir daí, quando o Python fizer a comparação entre o número 42 e 0 (linha 23), ela será verdadeira, já que seus ob_ival são iguais.

Extensões em C ou mesmo código Python com ctypes mal testados podem causar consequências imprevisíveis e bugs dificílimos de reproduzir, mesmo onde parece impossível. Mas também tem usos interessantes: Pense em um dos inúmeros jogos que suportam Python como Civilization IV, Battlefield 2 e Piratas do Caribe Online. É possível fazer um script usando o mesmo princípio que modifica, por exemplo, as variáveis de controle de vidas do jogador, posição etc.

Anúncios
Publicado em C, hack, Python. Tags: , , . 8 Comments »

Yahoo! Open Hack Day Brazil 2008

Neste fim de semana eu participei do Yahoo! Open Hack Day Brazil. O evento foi feito pelo Yahoo! no Senac de Santo Amaro e as pessoas se divertiram com as APIs abertas do Yahoo!, fazendo mashups e algumas outras maluquices. Durou das 08:00 de sábado até as 20:00 de domingo, 36 horas ininterruptas de hacking.

Só tenho coisas boas a dizer sobre o evento. O ambiente era muito confortável, a comida estava muito boa e fomos atendidos 100% do tempo, os hacks estavam muito legais, eles nos pegaram e levaram até estações de metrô e trem. Enfim, a organização do Yahoo! está de parabéns.

Eu como todo bom engenheiro eletricista fui ao HackDay munido de uma protoboard, muito fio, vários LEDs e mais alguns componentes, ainda sem uma idéia mas com a certeza que seria útil.

O pessoal do GruPy-SP devidamente uniformizado formou um time e aos poucos várias pessoas foram se juntando ao time. Éramos um time enorme, com 11 pessoas. Tivemos várias idéias, como pode ser visto no brainstorm abaixo:

Brainstorm do projeto

Brainstorm do projeto

O projeto era um eventômetro: um medidor de quanto burburinho um evento está gerando no Twitter e Flicker. Várias idéias foram dadas no brainstorm: um algoritmo de clustering para posts no Twitter e Flickr, usar o Quartz Composer e o Cocos2D para gerar uns efeitos legais, Yahoo! Blueprint para fazer uma aplicação para celular, eletrônica para sair do comum e mais um monte de outras coisas.

Eu fiquei com o hardware do nosso hack, junto com o Luiz Vitor Martinez Cardoso. Depois que terminamos o hardware eu fui para o script que baixava as informações do Twitter e Flickr.

Eu mostrando a protoboard

Eu mostrando a protoboard

Hardware do projeto

Hardware do projeto

A maluquice acima é um Arduino controlando os LEDs e o buzzer na protoboard. Os LEDs formam a palavra Yahoo! e piscam com uma frequência determinada pela quantidade de posts sobre o evento no Flickr na última hora. A quantidade de letras acesas do Yahoo! depende da quantidade de posts sobre o evento no Twitter na última hora. O buzzer tocava uma musiquinha cuja velocidade era a mesma com que os leds piscavam. Tudo era controlado pelo Arduino, uma plataforma aberta de hardware muito fácil de começar a fuçar, que recebia os dados do computador pela USB.

Usar os LEDs chamou muita atenção no evento, o tempo todo tinhamos jornalistas e outros participantes curiosos em saber o que era aquilo tão diferente.

Também tinhamos uma aplicação feita com Cocos2D que mostrava os últimos posts no Twitter e Flickr.

No final, não ganhamos os prêmios originalmente propostos, mas ganhamos outro prêmio. E a razão é bem simples: nosso projeto era bastante inútil, usava só uma API do Yahoo! (a do Flickr) e tinha um time muito maior que os outros. Mas ele era muito legal e diferente, então eles criaram mais 4 categorias e aí sim ganhamos um prêmio. A categoria foi chamada “What the hack was that?”, que reflete bem a surpresa com o nosso hack.

Concluindo, foi um fim de semana muito divertido, fiquei feliz com o nosso hack, com as pessoas que conheci, com os hacks legais apresentados e claro, com o prêmio.

Lameiro feliz com o prêmio

Lameiro feliz com o prêmio

Osciloscópios e jogos

Demo maravilhosa (download do áudio) feita num osciloscópio. Terceiro lugar na categoria shortfilm no Assembly 2007. E o cara tinha só 15 anos. Sensacional! Eu juro que um dia vou juntar dinheiro e ir pra Finlândia participar do Assembly, nem que seja só pra ficar olhando.

Pra falar a verdade eu queria mesmo era ver a demoscene brasileira no Campus Party Brasil.

Já que estamos falando de osciloscópios. Tennis for two, o segundo jogo usando display gráfico inventado. 1958.

OXO (1952) foi o primeiro, mas era um jogo da velha. Não achei vídeo no youtube. No entanto, existem emuladores, para os que estiverem interessados.

Publicado em hack. Tags: , , . 1 Comment »

Mais um Google Hack

Vejam este site.

E agora, esta busca no Google por IE7.

Já está em quinto. Mais um pouquinho (façam links nos seus sites para ajudar!) e o “Estou com sorte” é Firefox. Seria bem irônico. Será que o Google faz algo para combater este tipo de coisa?

Abraços
Leandro Lameiro

Publicado em hack, Uncategorized. Tags: . Leave a Comment »