quinta-feira, 4 de janeiro de 2018

Estava lendo agora sobre a vulnerabilidade nova que estão exploitando, e é bem legal!

Funciona assim: primeiro você executa um código desse jeito:

If (bigvalue < a.length) { value = a[bigvalue]; }

Se bigvalue for um valor maior que o tamanho do array, voce faria uma leitura fora de bounds, o que te permitiria ler qualquer valor da memória. Mas isso não deveria acontecer, por dois motivos: primeiro o if garante que você nunca executa aquele trecho; segundo mesmo que permitisse a cpu iria estourar um page fault porque você não tem permissão de ler aquele endereço.

SÓ QUE sua cpu tem execução especulativa. Se o a.length estiver fora do cache, a cpu precisa esperar uns 100 ciclos até o valor chegar. Para não ficar parada, ela sai executando o interior do if, e descarta essa execução quando o valor chega.

Em princípio isso não deveria ser acessível para o usuário, mas olha a pegadinha: como ele executou especulativamente o if, então agora o a[bigvalue] está no cache!

Agora você pode usar o seguinte código:

If (bigvalue < a.length) { value = a[bigvalue];
If (value&1 > 0) { x = a[100]; } else { x= a[200];}
}

Você controla o array a, então suponha que você forçou o array inteiro para fora do cache. Quando você executar esse código, a cpu vai tentar ler o a.length e travar (já que está fora do cache). Ela vai tentar executar especulativamente o if interno, e ela consegue (nesse ponto o a[bigvalue] está no cache e a cpu está executando especulativamente, então não checa as permissões). Dependendo do bit 0 do a[bigvalue] ela vai tentar ler o a[100] ou o a[200]. Eventualmente o valor de a.length chega e a cpu rebobina tudo porque o primeiro if falhou.

Agora vem a malandragem, você mede o tempo que leva para ler a[100] e a[200]. Só um deles foi parar no cache, aquele que ler mais rápido indica qual o valor do bit 0 de a[bigvalue]! Você acabou de ler um bit que não tinha permissão! Repete isso para os outros bits e você consegue ler qualquer valor da memória, até a senha do banco que está no outro tab do seu browser!

Para matar isso é fácil, só desligar o cache na bios. Mas aí seu computador de 2018 vai ficar mais lento que 386 rodando Windows 10, então ninguém vai fazer isso. Sacada muito boa, kudos para quem inventou a técnica.

sábado, 16 de dezembro de 2017

Star Wars - COM SPOILER
Não clique no "ver mais" se você ainda não viu o filme!
Sério, o filme sem spoiler é muito bom, qualquer coisinha que você ler vai diminuir a experiência!
(Abaixo da linha tracejada tem spoiler)


--------------------------------------
SPOILERS AHEAD
Separando em tópicos:
- Sim, um monte de gente morreu. Mas só teve uma morte que me deixou sentido, que foi o Ackbar. Poxa, um personagem tão legal morrendo off-screen? E não apenas mataram o Ackbar, destruíram também a nave dele, a Home One. Eu fiquei aqui pensando que essa não deveria ser a versão original do roteiro. Veja que todas as cenas com a almirante de cabelo roxo poderiam ter sido passadas para o Ackbar sem problemas, e o final seria muito melhor. O Ackbar sozinho na Home One, começa a ligar os hyperdrives, todo mundo achando que ele vai fugir, até que o Hux percebe que o Ackbar está virando na direção dele e fala "IT'S A TRAP!". Diz aí se não seria uma cena muito mais épica!
- (Se alguém pensou nisso, eu acho que mudaram para a almirante genérica porque a trama do Poe precisava que ele não conhecesse direito o comandante. Sem isso não teria o motim. A Ila Fox tem uma teoria mais simples de que essas cenas precisam de alguém que consiga atuar e mostrar emoção no rosto, e a máscara do Ackbar é meio limitada né. Não tem como fazer um fruto do mar ser expressivo).
- Eu posso estar sendo muito polêmico, mas agora eu acho que o Kylo Ren é um vilão melhor que o Vader. Sim, o Vader é malvadão e tal, mas eu tenho mais medo do Kylo Ren que do Vader. Veja, eu sei o que o Vader faz, ele faz malvadeza. O Kylo Ren eu não sei! Uma hora ele está amiguinho, na outra ele surta e fica contra você. Eu tenho muito mais medo de quem é imprevisível do que quem é consistente. O Vader sacaneava quem era subordinado, mas os chefes mesmo ele obedecia (tipo o Tarkin e o Imperador). O Kylo Ren não respeita mestre do light side, nem mestre do dark side, nem subordinado, nem ninguém. O Vader é lawful evil, o Kylo é chaotic.
- Inclusive, eu não sei se vocês tem experiência com gente surtada, mas ver isso de perto é um negócio assustador. E o Adam Driver conseguiu colocar isso no Kylo Ren. Naquela cena final dele com o Luke, o Kylo estava com o olhar do cara surtado (se você não sabe como é, procura no youtube o vídeo do Morre Diabo). Aquele é o olhar de quem está surtado, e é o olhar do Adam Driver na luta final (e eu acho que foi por isso que escolheram especificamente ele para interpretar o Kylo Ren, na série do Girls ele tinha uns momentos assim).
- Aliás, agora eu entendo as razões do Kylo Ren. Imagina a cena: você está de boa dormindo, aí de repente aquele tio que nunca casou entra no seu quarto à noite, com um olhar estranho e o pau de luz na mão. Quem não surtaria? E veja ainda que a escola Jedi é uma escola religiosa. O Luke era padre né. Super entendo a revolta do Kylo Ren.
- Sobre o Luke, achei muito bom como as dicas da cena final estavam todas lá, e mesmo assim eu não percebi. Quando o Luke aparece, ele está com a barba de outra cor, a barba está aparada ao invés de largada, o lightsaber está com a cor errada (azul ao invés de verde), estava tudo indicando que não era o Luke de verdade. Acho que o único que percebeu foi o C3PO, ele ia comentar alguma coisa mas o Luke interrompeu com uma piscadinha.
- Falando em pequenos detalhes, eu preciso ver o filme de novo para confirmar, mas eu posso jurar que no finalzinho, quando o Finn vai entrar na Falcon, ele abre uma gaveta/armário/something e de relance dá para ver os livros sagrados dos Jedi lá dentro. A Rey roubou os livros antes de fugir da ilha. Se realmente for isso que aconteceu, então a fala do Yoda fica ainda melhor ("não tem nada nessa árvore que a Rey já não tenha").
- Sobre a Rey, o diretor conseguiu encaixar bem as cenas desse filme com as do Império. Parece que todo lugar que é forte na Força de um lado também precisa ser do outro. O Yoda se escondeu em Dagobah, mas lá tinha uma caverna cheia de dark side; assim como na ilha desse filme. Achei bacana como as imagens se encaixam: o Luke vai procurar a resposta sobre o Vader e só encontra a si mesmo; a Rey vai procurar a resposta sobre seus pais e só encontra a si mesma. Talvez o diretor esteja sugerindo que o dark side é pensar mais em si mesmo que nos outros, o que bate com a mensagem da Rose antes de desmaiar.
- Inclusive eu estava com medo desse filme ser muito copiado do Império como o Force Awakens foi com o episódio 4, e a cena inicial da first order atacando a resistência em fuga me deixou apreensivo. Mas foi melhor que isso, o filme se descolou dos fatos e manteve só a temática em comum. No Império, o plano do Han de esconder com o Lando falha, o plano do Lando de vender o Luke e salvar o Han falha, o plano do Luke de derrotar o Vader e salvar todo mundo falha. O mesmo nesse filme, o motim do Poe falha, o plano do Finn de desligar o sensor falha, o plano da Rey de redimir o Kylo falha.
(Vou ver de novo no imax na quinta, depois eu complemento).
(Star Wars - Sem Spoiler)


Eu não gosto de futebol. Não gosto de jogar, não gosto de assistir, não vejo graça. E por isso, eu não entendo essa emoção toda que as pessoas sentem quando vão ao estádio e assistem ao time predileto fazer um gol. Para mim não faz sentido.
Mas eu imagino que deve ser parecido com assistir a uma pré-estréia de Star Wars. Eu lembro que na pré-estréia do episódio 2, quando o Yoda ligou o lightsaber na luta final a galera no cinema aplaudiu e gritou de emoção, como se fosse futebol mesmo.
Pois bem, nesse filme novo isso aconteceu umas cinco vezes. Teve gente gritando, gente aplaudindo, gente rindo, teve até gente chorando. Esse diretor sabe construir cenas de impacto, a impressão que me deu é que ele mandou todo mundo ir lá no tv tropes ler a entrada de Up To Eleven antes de interpretar os personagens.
Achei engraçado como tem muito de Star Trek nesse filme. Tem uma cena com um diálogo inteiro de technobabble que parece episódio de TNG. E Star Wars sempre teve escudos com campo de força na mitologia, mas dessa vez eles aparecem visualmente de um jeito que lembrou demais a Enterprise.
Dá para ver uma decisão consciente de expandir o público-alvo. Star Wars originalmente era coisa de menino. Mas agora tem cenas que foram claramente inseridas para o público feminino (e pelo alvoroço nas listas femininas de Star Wars que a Ila Fox participa, eu sei que funcionou). Eu achei curioso também que esse é o primeiro Star Wars vegetariano(!)
Mas o melhor do filme mesmo já estava escondido no trailer. A mensagem do trailer era "let the past die", e isso fizeram com maestria. Tanto o Force Awakens quanto o Rogue One eram filmes que olhavam para trás, o Last Jedi é um filme que olha para a frente. O foco não é nostalgia, pelo contrário, é destruir a nostalgia para reconstruir uma coisa nova.
Esse exercício de destruir para reconstruir melhor eu já vi antes, quando o Alan Moore criou o America's Best Comics. Ao invés de fazer super-heróis autofágicos como a Marvel e a DC fazem, ele foi na fonte original da mídia (pulps) e reconstruiu a partir da dali. Esse diretor fez o mesmo com Star Wars (a fonte original de Star Wars era Kurosawa, e esse filme tem momentos explícitos de Rashomon. Duna também. Tatooine era Arrakis, e nesse filme tem dilemas que são saídos de Duna, como a ética da presciência).
Enfim, recomendo de com força.

segunda-feira, 13 de novembro de 2017

Nessa última viagem eu aproveitei para comprar um fone de ouvido Bose QuietComfort 35 e foi de longe A MELHOR COMPRA DO ANO!

Primeiro a teoria. Eu uso fone de ouvido no trabalho para poder concentrar melhor, quanto menos ruído melhor. Mas é impossível tirar todo o ruído (acima de 0K sempre vai ter ruído de Boltzmann), e de qualquer modo minimizar ruído é errar o alvo, o que você quer mesmo é maximizar a relação sinal ruído (SNR)

Note que maximizar a SNR é fácil, basta aumentar o volume do fone! Se o volume estiver no talo, vai mascarar todo o ruído em volta. Mas isso não é bom porque detona seu ouvido. Outro truque é maximizar o espalhamento em frequência: tocar heavy metal mascara mais o que está em volta do que concerto de flauta.

Pois bem, o cancelamento ativo de ruido do QC35 é tão bom que eu ouço ZERO RUÍDO, mesmo com volume baixo, e tocando música clássica! Melhor fone da vida!

Para escolher esse modelo eu fui na B&amp;H e testei exaustivamente todos os modelos da loja (50+ marcas). Se fosse só pela SNR, empataram um da Bose, um da Sennheiser, e um da Sony. Mas como eu uso o dia todo, o desempate foi pelo mais confortável, a almofadinha do Bose era a mais suave.

Esse modelo é Bluetooth com um alcance super bom (consegui uns 40m sem paredes), mas você pode ligar por fio opcionalmente. Pelo fio tem um tiquinho de ruido analógico (trabalho na paulista né, ali é mar de radiação eletromagnética induzindo no cabo). Mas pelo Bluetooth é limpinho.

Ele sincroniza em dois devices ao mesmo tempo. Eu deixo o note e o celular (tem que deixar o celular porque literalmente não dá para ouvir o toque quando alguém te chama). Dá para parear por NFC para deixar a coisa ainda mais fácil.

O Bluetooth tem latência alta (200ms), o que não faz a menor diferença no meu caso. Mas se você for usar para jogar videogame competitivo é melhor usar pelo fio, aí a latência é zero.

A bateria carrega por USB e dura horrores (usei uma semana direto sem precisar carregar). Se quiser economizar bateria dá para desligar o cancelamento ativo. (O cancelamento passivo já é super bom, mas as baixas frequências acoplam na caixinha e ele acaba amplificando esse tipo de ruido. A impressão é que metade do serviço do cancelamento ativo é tirar esse ruído de baixa frequência. Ligado, o ativo tira tudinho)

A má notícia é que é caro horrores, e pelos reviews na internet parece que as partes plásticas são meio frágeis. Mas o resultado final é tão bom que estou disposto a comprar outro sempre que quebrar, é bom assim!

(Paguei uns 300 trumpinhos nele. A foca é para lembrar de focar no trabalho).


segunda-feira, 14 de agosto de 2017

Nesse mês o meu emulador BrMSX faz 20 anos! (sim, estamos velhos)

 Para comemorar, eu coloquei no github todos os fontes. Por todos eu quero dizer *todos mesmo*, eu fui nos backups, recuperei os fontes de todas as versões, e criei um repositório onde cada versão é um commit. Consegui salvar também as descrições originais; e até a data e hora de cada release.

 Curiosidades:

 - O primeiro commit é de 29 Aug 1997, o último é de 10 May 2000, foram quase 4 anos de desenvolvimento contínuo.

 - A maioria dos commits é de sábado e domingo (eu estudava durante a semana), mas aparentemente eu programava bastante de terça à tarde também.

 - O desenvolvimento da versão MSX2 começou em 11 Jul 1999 com release em 29 Jul 1999 (claramente eu esperei as férias para fazer uma mudança tão grande).

 - As primeiras linhas que eu escrevi não mudaram do começo ao fim! É a função readmem no brmsx.asm, se você der um git blame dá para ver que ela é a mesma desde o primeiro commit. Ela também é o caminho crítico, a função que mais é executada no emulador:

readmem:
mov esi,ecx
mov ebx,ecx
shr esi,13
and ebx,01fffh
mov esi,[offset mem+esi*4]
mov al,byte ptr [esi+ebx]
ret 

Para quem quiser se divertir, o link é o abaixo.

 https://github.com/ricbit/brmsx/commits/master

 (Deu um trabalhão do inferno reconstruir o repositório, espero que alguém mais goste haha)


sábado, 5 de agosto de 2017

Brinquedo do dia: fiz uma ferramenta de code coverage para Assembly Z80!

Mês passado eu tinha feito um parser de json em Assembly Z80, e fiz um monte de unit tests para garantir que estava direitinho. Mas aí eu pensei que só unit test não é suficiente, eu precisava também de code coverage para garantir que não esqueci de testar nenhum code path.

Escrever a ferramenta foi fácil, um plug-in em TCL pro openmsx e um script python para gerar o html. O que eu não esperava é que eu fosse realmente achar um bug com ele!

A história é que eu otimizei esse parser por espaço, e usei um monte de truques bem sujos para isso. Um deles é esse aí da foto, que eu chamo de "saltar no meio". Funciona assim: a rotina get_json_action tem dois entry points, um que chama com o registro A zerado (get_token_type), e outra que chama com o A não-zero (get_token_value).

O natural seria a primeira ter um XOR A para zerar o registrador, e a segundo um LD A,1 ou algo do tipo para setar com não-zero. Mas eu fiz diferente: usei os opcodes 3E AF em seguida. Se você executar a partir do 3E, o Z80 entende como LD A, 0xAF, que é não-zero. Se você rodar a partir do AF, ele entende como XOR A, que é zero. Eu saltei no meio do opcode e salvei alguns bytes assim.

O problema é que o wiring estava errado! Na hora de inicializar os ponteiros, eu fiz get_token_value = get_token_type + 1, quando deveria ser get_token_type - 1. E os unit tests não pegaram, porque, por coincidência, no turboR o registro A sempre estava não-zero naquele ponto. Ia passar batido, se a ferramenta de coverage não tivesse me avisado que aquele 3E nunca estava sendo executado!

Para quem ficou curioso, aqui o report mostrando o erro:

http://www.ilafox.com.br/ricbit/coverage_error.html 

E os scripts de coverage estão no repositório do msxjson:

https://github.com/ricbit/msxjson

sexta-feira, 4 de agosto de 2017

Fiz mais um open source de sucesso!

Antes de mais nada, como você define um open source de sucesso? Você poderia medir número de usuários ativos, ou algo nessa linha, mas a minha métrica é diferente: o código open source é de sucesso se ele foi reusado por mais pessoas em outros projetos. E aconteceu isso com meu script de músicas em formato VGM!

Lá por volta de 2014 eu estava com uma música de MSX que foi escrita no formato PLAY do BASIC, e precisava passar isso para Assembly. A maneira natural seria converter nota por nota, mas acabei tendo uma idéia melhor. O emulador openmsx permite que você crie plug-ins usando TCL, então eu criei um plug-in que chama o interpretador BASIC, toca a música, e captura o conteúdo dos registros do PSG e do OPLL.

Para mim já era o suficiente, mas aí eu pensei que poderia transformar isso num utilitário de uso geral, se eu guardasse o dump dos registros em um formato conhecido. Acabei fazendo um script que converte a música no formato VGM (video game music):

 https://github.com/ricbit/Oldies/blob/master/2014-11-grabfm/grabfm.tcl 

 Em 2015 o Grauw (da Holanda), pegou o meu script e fez uma versão que captura não só músicas em BASIC, mas em qualquer ambiente (jogos, por exemplo):

https://bitbucket.org/grauw/vgmplay-msx/annotate/536b64e03ffcc5c28e2b65deaa54f213b01abb90/tools/vgmrec.tcl?at=default&fileviewer=file-view-default 

 Depois o Niek (também da Holanda), pegou a versão do Grauw e adicionou suporte a outros chips de som (SCC, MSX-Audio e Moonsound):

 https://github.com/niekvlessert/openmsx_tcl_vgm_export/blob/master/vgmrecorder.tcl 

 Por fim, hoje esse código foi integrado na main branch do openmsx, agora ele é distribuído como plug-in oficial do emulador:

 https://github.com/openMSX/openMSX/blob/master/share/scripts/_vgmrecorder.tcl 

 Coloquei na web meio de farra e acabou sendo útil para um monte de gente :)

 (Na foto a fita original do Death Wish 3, que tem uma das melhores músicas do MSX. Na verdade essa fita de brinde num lote, o que eu tinha comprado mesmo era a fita do Goody, que é um jogos prediletos da Ila Fox).


terça-feira, 18 de julho de 2017

Depois de 11 anos, finalmente saiu a tradução completa do Hikaru no Go GBA!

A história é assim: em 2006 eu estava loucamente viciado em Go e ficava jogando no trem e no ônibus. Mas só tinham duas opções de Go portátil naquela época, um port do gnugo para Palm que era bem fraquinho, e o Hikaru no Go de Game Boy Advance que era mais forte e mais divertido.

Mas esse Hikago do GBA só tinha em japonês, como eu já tinha experiência em tradução de jogos resolvi fazer eu mesmo. Infelizmente, o japonês do jogo estava acima do meu nível, então eu publiquei na web tudo que eu tinha feito e deixei uma mensagem pedindo ajuda caso alguém tivesse interesse e habilidade.

Pois bem, em março desse ano um chinês me mandou um email falando que podia continuar a tradução. Eu dei as dicas, expliquei como funcionava o meu script de tradução, e ele se virou sozinho daí em diante. Ontem ele me mandou o resultado, todos os textos do jogo estão traduzidos agora! 

Agora faltam só os gráficos (tem uns kanjis desenhados como gráficos), e reprogramar alguns trechos do código (tipo a tela onde você insere seu nome, atualmente só dá para colocar kana).

Para quem quiser jogo, aqui está o ips para aplicar na rom original: 

http://www.ricbit.com/mundobizarro/hikago-2017-07-18.zip

E eu coloquei no github os scripts de tradução:

https://github.com/ricbit/hikago

(E fiquei impressionado como eu era diferente na época, hoje em dia nunca que eu ia usar java e xml para fazer script de tradução. Mas até que foi bom porque o chinês entende de java e conseguiu mudar sozinho um monte de partes do script.)


quinta-feira, 6 de julho de 2017

No episódio de hoje de "great minds think alike":
Um dos caras que eu recomendo seguir no twitter é o John Carmack (o programador original do Doom). Apesar de ser zilionário por causa do jogo, ele ainda é programador, porque é a coisa que ele mais gosta de fazer. E ele manja pra caramba de programação, então quando passa uma dica é bom parar pra ouvir, porque ele sabe do que está falando.
Dia desses ele twittou um artigo antigo sobre "implementações paralelas". Quem é, ou já foi, da área de jogos, certamente teve que otimizar código até o caroço; e normalmente o ciclo de desenvolvimento é algo do tipo: otimiza, testa, se ficou mais rápido git commit, goto 1.
Isso é legal, mas não é muito honesto. Você pode acabar fazendo uma otimização que desfaz um ganho que você teve alguns ciclos para trás e nem vai perceber. O Carmack, no artigo, menciona que o mais correto é manter todas as implementações em paralelo: você faz copy-and-paste no código, otimiza, e mantém as duas versões funcionando para ter comparação honesta.
Aí eu pensei: ahá! Foi exatamente o que eu fiz com o meu descompressor de gzip em Rust!
No meu caso, eu estava começando Rust do zero e simplesmente não sabia qual era o jeito mais rápido de otimizar. Então eu fiz várias implementações em paralelo, e eu troco na linha de comando qual implementação eu quero usar. Assim eu acho a combinação de implementações que dá o melhor ganho global!
Eu tenho quatro pedaços que posso trocar: um pedaço que "lê os bytes do disco" (entre aspas porque uma das implementações não lê nada, faz um mmap). Outro pedaço é o que converte bytes em bits, outro pedaço é o buffer de 32kb usado para manter a janela do LZ, e o último pedaço é que o escreve no disco de várias maneiras diferentes.
Os resultados não foram intuitivos at all pra mim. Eu achei que o mmap ia bombar, mas nem foi (provavelmente porque é melhor manter um buffer menor no L1 que sujar o cache com um pedação continuo de memória). Escrever no disco em uma thread separada foi ruim também (o overhead de comunicação entre as threads matava o ganho). Um buffer circular de 32kb não é necessariamente melhor que manter o arquivo todo em memória, depende de qual módulo está escrevendo no disco, e assim por diante.
Recomendo a técnica para todos que estão otimizando!
Aqui o meu codigo do rgzip:
https://github.com/ricbit/rgzip

terça-feira, 23 de maio de 2017

Ontem o alphago ganhou mais uma, vitória por meio ponto em cima do Ke Jie, campeão chinês. Antes que alguém ache que ele ganhou raspando, lembro que o algoritmo do alphago é tunado para maximizar a probabilidade de vitória, não para maximizar a diferença de pontos. Então é comum que a diferença seja pequena mesmo.
Na partida contra o Lee Sedol o alphago fez um monte de jogadas loucas e fora do comum. Eu estava esperando ver isso de novo, e aconteceu mesmo. Só que as jogadas doidas vieram do Ke Jie!
Isso faz sentido, e eu cantei essa bola na minha análise dos jogos contra o Sedol ano passado. O alphago tem dois estágios de processamento, uma rede neutral treinada com partidas profissionais, e um monte Carlo tree search. Se você fizer jogadas loucas, você neutraliza a rede neural, e briga só com o mcts. O Ke Jie estava tentando fazer isso (mas não foi o suficiente).
A impressão que eu tive na partida é que eu não sei mais jogar Go. Os dois estavam fazendo jogadas que até ano passado eram consideradas ruins (tipo invadir o sansan no começo do jogo, como assim?). Mas ouvindo os comentaristas parece que é assim que os outros estão jogando hoje em dia, eles aprenderam essas jogadas com o alphago e agora elas são mainstream.
Os comentaristas foram curiosos também, era claro que o ocidental comentando era mais forte que a chinesinha, mas eu entendia melhor os comentários dela (porque está mais próximo do meu nível, o ocidental é avançado demais pra mim). E a chinesinha falando era engraçado porque ela falava em inglês, mas com sotaque chinês, e usando termos técnicos em japonês (sente, dame, etc).
Também achei engraçada a contagem de pontos, a chinesa contou os pontos das brancas de um jeito muito louco, eu não entendi a conta dela haha. Mas o Ke Jie parecia estar entendendo.
A próxima é na quarta, vou assistir mas já não tenho muita esperança de ver o humano ganhando.


sábado, 13 de maio de 2017

Essa semana eu achei um bug em três compiladores diferentes!

Eu estava de boa otimizando o rgzip quando notei ele gerando um assembly bizarro. A função era equivalente a essa:

fn vecsum(v : &[u32]) -> u32 {
return v[0] + v[1] + v[2] + v[3] + v[4] + v[5];
}

O Rust tem como princípio sempre fazer bounds checking para evitar buffer overflow, isso é cool. Mas olha só o assembly que ele gera:

movq %rsi, %rax
testq %rax, %rax
je .LBB0_7
cmpq $1, %rax
je .LBB0_8
cmpq $3, %rax
jb .LBB0_9
je .LBB0_10
cmpq $5, %rax
jb .LBB0_11
je .LBB0_12

Um bound check para cada acesso! Claramente não precisava. Se você fizer só o bound check no v[5], então todos os outros garantidamente passam, porque o vetor é contínuo.

Reportei isso na comunidade de Rust e aí ficou mais bizarro ainda. Primeiro, o bug não aparece se você inverter a função:

return v[5] + v[4] + v[3] + v[2] + v[1] + v[0];

Segundo, não é um bug do Rust, é na camada mais embaixo do LLVM. A gente sabe disso porque um código equivalente em C++ no clang gera o mesmo bug:

struct Vec {
int len;
int* data;
};

inline int get(struct Vec* vec, int i) {
if (i < vec->len) {
return vec->data[i];
} else {
abort();
}
}

int sum5(struct Vec* vec) {
return get(vec, 0) + get(vec, 1) + get(vec, 2) + get(vec, 3) + get(vec, 4) + get(vec, 5);
}

Por fim, o bug não é só no LLVM, ele aparece também no gcc e o no icc! Confiram:


Já foi tudo reportado, agora é só esperar alguém consertar. Idealmente eu mesmo consertaria, mas infelizmente a vida é curta :(



sábado, 29 de abril de 2017

Eu estava com vontade de escrever um descompressor de gzip do zero, também estava com vontade de aprender Rust, aí pensei: por que não os dois ao mesmo tempo? O resultado é o rgzip:
A parte gzip foi relativamente simples, eu só segui os RFCs. Por dentro ele é um LZ codificado com Huffma, não tem muito segredo. Mas tem duas coisas curiosas sobre o formato.
A primeira é que ficou claro para mim que o Phil Katz escreveu a primeira versão em assembly. Tem partes do formato que são difíceis de escrever em linguagens de alto nível, mas são triviais para quem tem rot e shl.
A segunda é que o formato permite emular RLE, usando janelas para o futuro. Por exemplo, se o arquivo começa com AB, você pode colocar uma janela "volta 2 e copia 6", aí o output é ABABABAB.
Sobre a linguagem Rust, achei bem bacana. A idéia foi tentar construir uma linguagem focada em segurança, onde é impossível programar um bug. Ele faz isso colocando restrições bem severas no tipo de código que você consegue escrever, e usando compile-time checks para garantir isso.
Por exemplo, em C++ você pode fazer isso:
int *func () {
int x = 1;
return &x;
}
Esse código vai dar segfault porque x estava no stack, quando a função retorna o x já morreu. Em Rust isso nem compila, ele saca que o lifetime do &x está restrito ao escopo da função e não deixa você retornar o ponteiro.
Outro problema do C++ é assim:
class X {
X(int *p) : p_(p) {}
int *p_;
};
int *p = new int;
X x(p);
E aí, quem vai dar o delete *p, o X() ou quem chamou o X()? O Rust resolve isso com sintaxe própria para dizer quem é o dono do ponteiro. (E como ele sabe quem é o dono, você nem precisa dar o delete. Ele deleta sozinho quando o dono sai do escopo).
Tem mais um monte de manhas, achei bem legal. Outras características são:
- Ele usa o sistema de type inference do Haskell, e tem muitas ferramentas de programação funcional disponíveis.
- O const é invertido em relação ao C++. Por default, todas as variáveis são const, se você quiser alterar o valor de uma variável precisa declarar como mut (inspirado em linguagens funcionais provavelmente).
- A sintaxe lembra bastante o Go, mas ele possui generics, o que é uma grande vantagem! Generics + type inference permite pegar um monte de erros em tempo de compilação.
- Além de generics, ele tem também macros! Mas não são as macros podres do C, ao invés de preprocessar texto, as macros do Rust atuam em cima da syntax tree do Rust. Muito mais legal e ainda permite um tipo de "template metaprogramming".
- Ele não tem o tipo int! Todos os tipo precisam ser explicitamente declarados. Ao invés de int você pode usar u32 ou i16.
- E falando nisso, ele não absolutamente nenhum tipo de cast automático, nem para variáveis inteiras. Você precisa explicitamente fazer um cast para copiar um valor u8 para uma variável u32. Isso vem da filosofia dele de ser o mais explícito possível.
- A stdlib dele é pequena, mas tudo bem porque ele tem um pip-like no pacote default. É só dar um include que ele baixa e instala a lib externa sozinho.
- Em geral, é mais difícil programar em Rust que em Go, C++ ou Python. Mas tem um motivo, é que você é obrigado a escrever um programa sem bugs sempre, senão não compila. Um monte de coisas nas outras linguagens só são fáceis porque você pode ignorar side-effects ou tratamento de erros.
- Inclusive, Rust não tem exceptions. Todo o tratamento de erros é feito com o Option<> e Result<> do Haskell (que colocaram recentemente no java também). Acho isso muito, muito melhor que retornar tuplas como no Go.
- Ele não tem goroutines, mas tem um sistema de threads usando canais para concorrência. Ainda não testei, mas o doc diz que ele pega deadlocks em tempo de compilação. Veremos.
- Ele também não tem garbage collector, mas nem precisa porque o sistema de RAII, lifetime e ownership explicito toma conta da memória sem precisar de gc.
Recomendo dar uma olhada, achei promissor. Já está na versão 1.x então a linguagem está mais ou menos estável. Eu lembro que programei bastante no Go 0.x e os meus programas dessa época nem compilam mais, em Rust stable isso não deve acontecer.


quarta-feira, 7 de setembro de 2016

Custa nada avisar a galera: a brincadeira da vez é postar uma foto da primeira mensagem que você recebeu no gmail, pra mostrar como você é fodão e usava internet no tempo das cavernas e tal. NÃO FAÇAM ISSO.

Talvez você não saiba, mas essa é uma das perguntas de segurança da sua conta. Se por algum motivo você ficar com a conta travada (por exemplo, mudou de celular, aí não consegue receber o otp, e o email alternativo era um do ig que nem existe mais), então o único jeito de destravar a conta é ligando no suporte, e eles vão te fazer perguntas para confirmar. Por exemplo, qual era seu email alternativo e qual a data aproximada em que você criou a conta.

Se você postar a foto do seu gmail, você está dando metade da informação de graça pro hacker. Não faça isso.

(De quebra, não custa nada ir na página de segurança e imprimir uns otps para usar quando você estiver sem celular. Pode acontecer de você ter wifi mas não ter 3g, por exemplo numa viagem, e você não quer ficar travado para fora da conta por isso).


domingo, 7 de agosto de 2016

No desfile dos atletas a Ila Fox estava falando que deve ser emocionante ser um dos atletas que vai representar o seu país, aí disse "ah, eu sei mais ou menos qual é a sensação!".
Como assim?, ela perguntou. Veja, eu nunca fui na olimpíada de esporte, mas já fui na olimpíada de matemática! Foi na Olimpíada Brasileira em 1993, onde ganhei medalha de prata.
A parte do mais ou menos é que eu nunca representei o país de fato. Quem ganhava medalha na olimpíada brasileira era indicado para ir na Olimpíada Internacional, e de fato eles me chamaram.
Mas tinha um detalhe: a comissão organizadora não tinha dinheiro para pagar a minha passagem até Hong Kong, onde seria o evento! Como eu também não tinha dinheiro, acabei cedendo minha vaga para o próximo na fila.
Hoje em dia seria mais fácil, só ir num crowdfunding qualquer e fazer uma vaquinha. De fato, sempre que eu vejo algum aluno pedindo grana para ir em olimpíada eu faço questão de contribuir.
De curiosidade, eu resgatei do backup a prova original da época. Eu fechei essa prova, fiz todas as questões, mas peguei a medalha de prata no desempate. (Quem ganhou o ouro naquele ano foi o Douglas Cancherini).


quinta-feira, 4 de agosto de 2016

Não sei se já mencionei, mas minha mãe costumava bater em mim para sair de casa. Olha só, eu tinha um microcomputador e uma biblioteca grande, sair de casa pra quê?
Claro que isso foi antes do Pokemon Go. Agora eu já saí de casa dois dias seguidos! A Ila Fox até achou que eu deveria escrever um diário, então aí vai:
DIA 1
Eu estava no Uber voltando pra casa quando o jogo saiu. Decidi que ia jantar fora e capturar pokemons no caminho, então peguei meu charmander starter e fui.
No restaurante mexicano já peguei um Poliwag. Os garçons juntaram todos em volta pra ver. Um deles até mencionou "tô ligado esse aí, vira Poliwhirl" (tava manjando mais que eu!)
Depois da janta fui até a igreja onde tinha um marcador, eu não sabia o que fazer com o marcador. Tinha um tiozinho na frente da igreja também. Nós trocamos uma idéia e descobrimos, tinha que girar o marcador, libera pokebola. Boa!
Tinha um marcador rosinha no mapa e resolvi ver o que era. No caminho, passei por uns cinco jogadores (e isso foi tipo uma hora depois do jogo ter lançado). Felizmente o bairro aqui é seguro para andar, o aluguel é caro mas pelo menos dá para caçar pokemon no sossego.
O marcador rosa eu descobri que era spawn de pokemon, alguém usou um item ou something. Tinha um Pinsir na frente de um restaurante coreano que eu nem sabia que existia (nota mental, voltar lá e ver se posso experimentar tô-mandu-ku).
Segui em outra direção, vi um Caterpie mas não conseguia clicar nele no jogo. Não ia de jeito nenhum. Achei que tinha tanta gente jogando que ou o server baleiou, ou a ERB da tim não deu conta de segurar tanto celular ligado.
Tinha um grupinho na esquina e resolvi perguntar se para eles funcionava. Um dos guris me explicou que às vezes acontece isso, tem que sair e entrar de novo no jogo. Testei e funcionou! Perguntei se os guris já se conheciam, nope, todos eles tinham se conhecido ali na esquina. Avisei que tinha um Pinsir três quarteirões pra baixo e eles foram lá contentes.
Terminei a ronda e voltei pra casa. Entrando no elevador eu vi um gurizinho saindo com celular na mão. Batata! Perguntei se ele tinha pego Pikachu, e ele disse que sim! Eu estava disposto a sair de novo se fosse pra pegar Pikachu, então perguntei onde que ele pegou. "Foi em Times Square", ele disse. - "Times Square, New York?" - "Isso!" - "Dammit, muito longe!"
Achei que tinha acabado pelo dia, mas dei sorte, tinha um Staryu no banheiro! Esse foi o último do dia.
DIA 2
Por motivos de força maior eu fui almoçar às 16h30 apenas. Já que ia sair, aproveitei para caçar. No caminho já vi um guri caçando pokemon de skate. Mano, eu tenho medo de deixar o celular cair enquanto estou andando, imagina andando de skate. Mas o guri tava de boa.
Na esquina, outro guri. "Pegou pikachu?", eu perguntei, e ele "já peguei, foi meu primeiro!". Como assim primeiro? "Quando você começa o jogo, se você fugir dos três iniciais aparece um Pikachu", ele respondeu, olhando com aquela cara de "adultos são burros mesmo".
Depois de mais meia dúzia de Pokemons, cheguei no nivel 5, agora posso ir em estádio! Fui em um aqui perto, na hora de escolher o time eu fiquei com dó e peguei o time vermelho. Nesse bairro ninguém vai escolher o time vermelho.
Continuei até uma praça onde tem dois pokestops juntos. Tinha uma galera ali, tipo mais de vinte guris. Todo mundo caçando pokemon quando eu olho pro lado e vejo um filhote de gato. Gato cinza, bonitão, sedoso, não resisti e capturei ele. Perguntei se era de algum dos vinte guris, ninguém reconheceu, então fui pra casa.
Chegando em casa, diagnóstico. Gata filhote, porém gordinha, mansa, sem medo de humanos, provavelmente fugiu de alguém. Nós a batizamos temporariamente de Vesicula. Side mission: achar o dono!
Ila e eu voltamos para a praça dos pokestops. Notamos que agora, além dos caçadores de pokemons, estava cheio de casais adolescentes. Deduzimos que falaram para os pais que iam caçar pokemon, espertos eles.
Batemos de porta em porta até que nos indicaram uma casa no fim de uma vila. Lá dentro tinha a dona Lindalva falando que a gata sumiu. Nós achamos, peraí que vamos trazer!
Voltamos para casa, colocamos a Vesicula em uma caixa de transporte, e a levamos até a dona Lindalva. Nesse meio tempo os filhos tinham chegado da escola. O menorzinho falou "olha a gata voltou!". Depois meteu uma bifa na gata e disse "não foge mais!". A Vesicula olhou pra mim com raiva e eu pensei "Desculpa Vesicula, eu não sabia".
Antes de ir para casa, passei na praça dos pokestops com a caixa de transporte vazia e anunciei pra galera "trouxe uma caixa para transportar os pokemons capturados!". Todo mundo riu. つづく


sexta-feira, 29 de julho de 2016

No fim de semana nós fomos jantar com o Lucas Radaelli, que tinha acabado de voltar de um torneio de xadrez (ele gosta de xadrez porque é um jogo onde um cego pode competir de igual para igual com alguém que enxerga).
Só que aí ele me pediu pra explicar quais são as jogadas típicas do Go, e eu pensei, raios, como eu explico isso? O jeito foi descrever com os coordenadas, eu fechei os olhos e comecei assim:
"Uma jogada típica é tentar fazer dois olhos. Vou falar as coordenadas, primeiro x, depois y (que burro eu). Um olho é uma configuração onde os brancos estão em 0-1, 1-1, 1-0, e os pretos estão em 0-2, 1-2, 2-1, 2-0. Aí o preto joga em 0-0 e come, porque cerca as brancas por dentro. Mas se os brancos estiverem em 0-1, 1-1, 2-1, 3-1, 1-0, 3-0, então mesmo que o preto esteja cercando por fora, não tem como comer, porque teria que jogar em 0-0 e 2-0 ao mesmo tempo, e ele só joga uma por vez"
No fim ele entendeu, mas não sei se na hora alguém sacou por que eu estava me achando burro. É que eu mencionei que ia falar primeiro o x e depois o y, mas isso era irrelevante! Se você imaginar o tabuleiro transposto, dá na mesma. Eu só percebi isso depois que já tinha falado haha.


quinta-feira, 28 de julho de 2016

Eu já passei dos 40 anos, então já deu tempo de acumular um bom repertório de histórias bizarras que aconteceram comigo. Já levei mordida de leão na África, já profanei tumba de 2400 anos na Turquia, e daí em diante.
Mas tem uma história que ninguém bota fé que aconteceu de verdade, que é a história do furacão que levou o circo embora.
Teve uma época que eu morei na Praia Grande (litoral de sp). Eu era pequeno e não tenho muitas lembranças da época. Mas uma das poucas lembranças que eu ainda tenho, é de que teve um fim de semana onde passou um furacão pela cidade, tão forte que levou embora o circo que estava montado na praia.
Eu até estava achando que era memória falsa, mas aí eu liguei pra minha mãe e ela confirmou a história. E mais, não só o furacão levou o circo, como levou as janelas do nosso apartamento junto. Começou a entrar loucamente água do mar pela janela, inundou tudo, e nós tivemos que ficar um tempo na casa da vizinha.
Aí clicou! Disso eu lembro sim, e eu lembro porque a vizinha colecionava Tio Patinhas, enquanto o furacão comia solto eu estava lendo os gibis dela. E vou além, lembro que um dos gibis que tinha saído naquela época era um especial do Peninha com a primeira aparição do Biquinho.
Então agora eu tenho um timeframe: isso foi por volta de julho de 1982. Agora que eu tenho uma data, dá pra ir na biblioteca procurar os jornais da época, algum deles deve ter a notícia de quando o furacão levou o circo 


quarta-feira, 20 de julho de 2016

Tava aqui estudando grego e aprendi uma frase muito útil: MOLON LABE.
Consta que o Leonidas estava de prontidão na passagem das Thermopilas, quando o Xerxes chegou e anunciou "Renda-se, e me dê suas armas". Aí o Leonidas respondeu MOLON LABE, que do grego arcaico significa "vem pegar".
Muito útil para ser usada em uma variedade de contextos!


domingo, 17 de julho de 2016

Falando em tradução, mês passado fizemos um encontro do povo do LSI/USP, e eu aproveitei a oportunidade para pegar um autógrafo do Arnaldo Oka no meu Hikaru no Go #1 (depois da USP, o Oka virou o mestre tradutor dos mangás da JBC).

Em retrospecto, trabalhar no LSI foi muito importante num aspecto pouco usual. Eu estudei eletrônica num dos melhores colégios técnicos do país, depois estudei engenharia num dos melhores cursos do país. O efeito colateral disso é que com tanta overdose de exatas, eu tinha tudo para ser um desses babacas que acha gente de humanas só serve para fazer miçanga.

Felizmente, trabalhar em um laboratório interdisciplinar curou isso. Curou tão bem, que hoje em dia eu sou casado com a Ila Fox, que é formada em artes plásticas. Fora do trabalho, eu passo mais tempo com gente de humanas do que com gente de exatas!



Povo me perguntou se a cor dos escudos no Aleste 2 do MSX faz alguma diferença. Eu não sabia, então fui procurar o manual, e olha só! Não apenas faz, como os escudos tem até nome! Aqui o original e minha tradução:
「シールド・イエロー」   防御のみ。250の耐久力があります。
「サポート・レッド」    耐久力200。ボスキャラの攻撃を受けると誘導弾となってボスキャラにダメージを与えます。
「アシスト・ブルー」    耐久力150。通常弾を貫通弾にします。
「グラヴィ・ティ・ブラック」耐久力120。アレスタ2の攻撃力が50%UPします。
"shield yellow" Defense only, has 250 durability.
"support red" Durability 200, becomes a guided missile that damages boss ships when hit by the boss ship.
"assist blue" Durability 150, normal bullets become piercing bullets
"gravity black" Durability 120, increase offensive ability of Aleste 2 by 50%.
Thx Tornado pela ajuda na tradução.