Skip to content
Browse files

Fixed Thread#run, added corruption detection to rbc files

* Thread#run was confusing the Thread scheduler, cause things the VM
  to quit running.
* Added corruption detection to .rbc files in the form of a SHA1
  hash placed in the .rbc, just after the header.
  • Loading branch information...
1 parent b3665e3 commit 41831976d25a4d5a8e26673199276098cc45b4d3 @evanphx evanphx committed Dec 13, 2007
View
2 Rakefile
@@ -400,7 +400,7 @@ desc "Remove all stray compiled Ruby files"
task :pristine do
FileList['**/*.rbc'].each do |fn|
next if /^runtime/.match(fn)
- next if /require\/require_spec_.\.rbc/.match(fn)
+ next if %r!fixtures!.match(fn)
next if %r!lib/compiler1!.match(fn)
FileUtils.rm fn rescue nil
end
View
2 kernel/core/compile.rb
@@ -2,7 +2,7 @@ module Rubinius
# This const controls what the lowest version of compiled methods we can
# allow is. This allows us to cut off compability at some point, or just
# increment when major changes are made to the compiler.
- CompiledMethodVersion = 5
+ CompiledMethodVersion = 6
end
module Compile
View
2 kernel/core/thread.rb
@@ -145,7 +145,7 @@ def self.sleep(duration = nil)
# FIXME: the if statment breaks everything (non-deterministic failures in test suite)
Scheduler.send_in_microseconds(chan, (duration * 1_000_000).to_i) #if duration
- chan.receive
+ out = chan.receive
return Time.now - start
end
View
16 lib/compiler1/bytecode/assembler.rb
@@ -23,12 +23,12 @@ def initialize(name)
attr_accessor :location, :set
end
- def initialize(literals=[], name=nil, state=RsLocalState.new)
+ def initialize(literals=[], name=nil, state=Compiler1::RsLocalState.new)
@name = name
reset(literals, state)
end
- def reset(literals=[], state=RsLocalState.new)
+ def reset(literals=[], state=Compiler1::RsLocalState.new)
@labels = Hash.new { |h,k| h[k] = Label.new(k) }
@current_op = 0
@output = []
@@ -119,7 +119,9 @@ def sorted_exceptions
def assemble(str)
puts str if ENV["DEBUG_ASSEMBLER"]
- str.each { |l| parse_line l }
+ # HACK Using str.each or str.each_line causes each to not split on newlines
+ # for some reason.
+ str.split("\n").each { |l| parse_line l }
translate_labels
if ent = @source_lines.last
ent[1] = @current_op
@@ -142,7 +144,7 @@ def literals_as_tuple
end
def bytecodes
- enc = Bytecode::InstructionEncoder.new
+ enc = Compiler1::Bytecode::InstructionEncoder.new
str = @output.inject("") { |a,i| a + enc.encode(*i) }
end
@@ -527,9 +529,9 @@ def parse_operation(*parts)
return
end
- if Bytecode::InstructionEncoder::OpCodes.include?(op)
- if Bytecode::InstructionEncoder::IntArg.include?(op)
- if Bytecode::InstructionEncoder::TwoInt.include?(op)
+ if Compiler1::Bytecode::InstructionEncoder::OpCodes.include?(op)
+ if Compiler1::Bytecode::InstructionEncoder::IntArg.include?(op)
+ if Compiler1::Bytecode::InstructionEncoder::TwoInt.include?(op)
fir = parts.shift.to_i
add op, fir, parts.shift.to_i
else
View
5 lib/compiler1/bytecode/compiler.rb
@@ -5,6 +5,7 @@
require 'compiler1/translation/states'
module Compiler1
+
module Bytecode
class MethodDescription
@@ -36,15 +37,15 @@ class Compiler
def self.compile_file(path, flags=nil)
sexp = File.to_sexp(path, true)
- comp = Bytecode::Compiler.new
+ comp = Compiler1::Bytecode::Compiler.new
comp.import_flags(flags) if flags
desc = comp.compile_as_script(sexp, :__script__)
return desc.to_cmethod
end
def self.compile_string(string, flags=nil, filename="(eval)", line=1)
sexp = string.to_sexp(filename, line, true)
- comp = Bytecode::Compiler.new
+ comp = Compiler1::Bytecode::Compiler.new
comp.import_flags(flags) if flags
state = RsLocalState.new
state.uses_eval = true
View
14 lib/compiler1/bytecode/plugins.rb
@@ -50,7 +50,7 @@ def run(recv, meth, args, block)
end
end
-class MetaOperatorPlugin < Bytecode::Compiler::Plugin
+class MetaOperatorPlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_math
@@ -80,7 +80,7 @@ def handle(recv, meth, args, block)
end
-class SystemMethodPlugin < Bytecode::Compiler::Plugin
+class SystemMethodPlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_system
@@ -149,7 +149,7 @@ def handle(recv, meth, args, block)
end
end
-class NamedSendPlugin < Bytecode::Compiler::Plugin
+class NamedSendPlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_send_method
@@ -183,7 +183,7 @@ def handle(recv, meth, args, block)
end
end
-class FieldAccessPlugin < Bytecode::Compiler::Plugin
+class FieldAccessPlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_field_access
def push_index(idx)
@@ -217,7 +217,7 @@ def handle(recv, meth, args, block)
end
end
-class TypeCoercePlugin < Bytecode::Compiler::Plugin
+class TypeCoercePlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_coerce
def handle_fixnum(recv, meth, obj)
@@ -336,7 +336,7 @@ def handle(recv, meth, args, block)
=begin
-class FastTimesPlugin < Bytecode::Compiler::Plugin
+class FastTimesPlugin < Compiler1::Bytecode::Compiler::Plugin
flag :fast_times
@@ -366,7 +366,7 @@ def handle(recv, meth, args, block)
this is premature
-class FastSplatAccess < Bytecode::Compiler::Plugin
+class FastSplatAccess < Compiler1::Bytecode::Compiler::Plugin
def process(recv, meth, args)
return false if meth != :[] or args.size != 2
return false if recv.first != :lvar
View
8 lib/compiler1/bytecode/rubinius.rb
@@ -16,7 +16,7 @@ def to_cmethod
puts @assembly
end
- asm = Bytecode::Assembler.new(@literals, @name, @state)
+ asm = Compiler1::Bytecode::Assembler.new(@literals, @name, @state)
begin
stream = asm.assemble @assembly
rescue Object => e
@@ -32,7 +32,7 @@ def to_cmethod
p stream
end
- enc = Bytecode::InstructionEncoder.new
+ enc = Compiler1::Bytecode::InstructionEncoder.new
bc = enc.encode_stream stream
lcls = @state.number_of_locals
iseq = bc.data.dup(InstructionSequence)
@@ -43,7 +43,7 @@ def to_cmethod
idx = nil
if @primitive.kind_of? Symbol
- idx = Bytecode::Compiler::Primitives.index(@primitive)
+ idx = Compiler1::Bytecode::Compiler::Primitives.index(@primitive)
unless idx
raise ArgumentError, "Unknown primitive '#{@primitive}'"
end
@@ -157,7 +157,7 @@ def tuple_of_syms(ary)
end
def primitive_to_index(sym)
- Bytecode::Compiler::Primitives.index(sym) + 1 # add 1 for noop padding
+ Compiler1::Bytecode::Compiler::Primitives.index(sym) + 1 # add 1 for noop padding
end
end
end
View
BIN runtime/stable/bootstrap.rba
Binary file not shown.
View
BIN runtime/stable/compiler1.rba
Binary file not shown.
View
BIN runtime/stable/core.rba
Binary file not shown.
View
BIN runtime/stable/loader.rbc
Binary file not shown.
View
BIN runtime/stable/platform.rba
Binary file not shown.
View
4 shotgun/lib/archive.c
@@ -145,7 +145,7 @@ OBJECT archive_get_object(STATE, const char *path, char* name, int version) {
zip_fclose(zf);
zip_close(za);
- ret = cpu_unmarshal(state, str, version);
+ ret = cpu_unmarshal(state, str, (int)st.size, version);
free(str);
return ret;
}
@@ -178,7 +178,7 @@ OBJECT archive_get_object2(STATE, archive_handle za,
zip_fclose(zf);
- ret = cpu_unmarshal(state, str, version);
+ ret = cpu_unmarshal(state, str, (int)st.size, version);
free(str);
return ret;
View
4 shotgun/lib/bytearray.c
@@ -86,6 +86,10 @@ void iseq_flip(STATE, OBJECT self) {
f = object_size(state, self);
buf = (uint8_t*)bytearray_byte_address(state, self);
ibuf = (uint32_t*)bytearray_byte_address(state, self);
+
+ /* The first thing can't be a noop */
+ sassert(*ibuf);
+
/* A sanity check. The first thing is always an instruction,
* and we've got less that 1024 instructions, so if it's less
* it's already been flipped. */
View
3 shotgun/lib/cpu.h
@@ -180,7 +180,7 @@ inline void cpu_save_registers(STATE, cpu c, int stack_offset);
OBJECT exported_cpu_find_method(STATE, cpu c, OBJECT klass, OBJECT name, OBJECT *mod);
-OBJECT cpu_unmarshal(STATE, uint8_t *str, int version);
+OBJECT cpu_unmarshal(STATE, uint8_t *str, int len, int version);
OBJECT cpu_marshal(STATE, OBJECT obj, int version);
OBJECT cpu_unmarshal_file(STATE, const char *path, int version);
bstring cpu_marshal_to_bstring(STATE, OBJECT obj, int version);
@@ -208,6 +208,7 @@ OBJECT cpu_thread_get_task(STATE, OBJECT self);
void cpu_thread_switch_best(STATE, cpu c);
void cpu_thread_schedule(STATE, OBJECT self);
void cpu_thread_run_best(STATE, cpu c);
+void cpu_thread_force_run(STATE, cpu c, OBJECT thr);
void cpu_task_disable_preemption(STATE);
void cpu_task_configure_premption(STATE);
View
16 shotgun/lib/cpu_instructions.c
@@ -80,10 +80,8 @@ OBJECT cpu_open_class(STATE, cpu c, OBJECT under, OBJECT sup, int *created) {
string_append(state, s3, s2);
s4 = string_to_sym(state, s3);
module_set_name(val, s4);
- // printf("Module %s name set to %s (%d)\n", _inspect(val), rbs_symbol_to_cstring(state, s4), FIXNUM_TO_INT(class_get_instance_fields(val)));
} else {
module_set_name(val, sym);
- // printf("Module %s name set to %s (%d)\n", _inspect(val), rbs_symbol_to_cstring(state, sym), FIXNUM_TO_INT(class_get_instance_fields(val)));
}
module_const_set(state, under, sym, val);
sup_itr = sup;
@@ -92,7 +90,7 @@ OBJECT cpu_open_class(STATE, cpu c, OBJECT under, OBJECT sup, int *created) {
}
OBJECT cpu_open_module(STATE, cpu c, OBJECT under) {
- OBJECT sym, _lit, val;
+ OBJECT sym, _lit, val, s1;
int _int;
next_literal;
@@ -102,7 +100,17 @@ OBJECT cpu_open_module(STATE, cpu c, OBJECT under) {
if(!RTEST(val)) {
val = module_allocate_mature(state, 0);
module_setup_fields(state, val);
- module_set_name(val, sym);
+
+ if(c->enclosing_class != state->global->object) {
+ s1 = symbol_to_string(state, module_get_name(c->enclosing_class));
+ s1 = string_dup(state, s1);
+ string_append(state, s1, string_new(state, "::"));
+ string_append(state, s1, symbol_to_string(state, sym));
+ module_set_name(val, string_to_sym(state, s1));
+ } else {
+ module_set_name(val, sym);
+ }
+
module_const_set(state, under, sym, val);
module_setup_fields(state, object_metaclass(state, val));
module_set_parent(val, under);
View
65 shotgun/lib/cpu_marshal.c
@@ -6,6 +6,8 @@
#include "tuple.h"
#include "bignum.h"
#include "float.h"
+#include "sha1.h"
+
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
@@ -46,13 +48,17 @@ static void _add_object(OBJECT obj, struct marshal_state *ms) {
static OBJECT unmarshal(STATE, struct marshal_state *ms);
static void marshal(STATE, OBJECT obj, bstring buf, struct marshal_state *ms);
-#define append_c(ch) bconchar(buf, ch)
-static void _append_sz(bstring buf, unsigned int i) {
- char bytes[4];
+static void int2be(unsigned int i, unsigned char bytes[4]) {
bytes[0] = ( i >> 24 ) & 0xff;
bytes[1] = ( i >> 16 ) & 0xff;
bytes[2] = ( i >> 8 ) & 0xff;
- bytes[3] = i & 0xff;
+ bytes[3] = i & 0xff;
+}
+
+#define append_c(ch) bconchar(buf, ch)
+static void _append_sz(bstring buf, unsigned int i) {
+ unsigned char bytes[4];
+ int2be(i, bytes);
bcatblk(buf, bytes, 4);
}
#define append_sz(sz) _append_sz(buf, (unsigned int)sz)
@@ -428,8 +434,9 @@ static OBJECT unmarshal(STATE, struct marshal_state *ms) {
o = Qfalse;
break;
default:
+ o = Qnil;
printf("Unknown marshal type '0x%x' at %d!\n", tag, ms->consumed);
- abort();
+ sassert(0);
}
return o;
}
@@ -487,23 +494,34 @@ OBJECT cpu_marshal(STATE, OBJECT obj, int version) {
}
bstring cpu_marshal_to_bstring(STATE, OBJECT obj, int version) {
- bstring buf;
+ bstring buf, stream;
struct marshal_state ms;
+ unsigned char cur_digest[20];
ms.consumed = 0;
ms.objects = ptr_array_new(8);
+
+ stream = cstr2bstr("");
+ marshal(state, obj, stream, &ms);
+ sha1_hash_string((unsigned char*)bdata(stream), blength(stream), cur_digest);
buf = cstr2bstr("RBIX");
+
_append_sz(buf, version);
- marshal(state, obj, buf, &ms);
+ bcatblk(buf, (void*)cur_digest, 20);
+ bconcat(buf, stream);
+ bdestroy(stream);
+
ptr_array_free(ms.objects);
- return buf;
+ return stream;
}
OBJECT cpu_marshal_to_file(STATE, OBJECT obj, char *path, int version) {
bstring buf;
FILE *f;
struct marshal_state ms;
+ unsigned char cur_digest[20];
+ unsigned char bytes[4];
f = fopen(path, "wb");
if(!f) {
@@ -514,11 +532,18 @@ OBJECT cpu_marshal_to_file(STATE, OBJECT obj, char *path, int version) {
ms.objects = ptr_array_new(8);
buf = cstr2bstr("");
- _append_sz(buf, version);
+
marshal(state, obj, buf, &ms);
+ sha1_hash_string((unsigned char*)bdata(buf), blength(buf), cur_digest);
/* TODO do error chceking here */
fwrite("RBIX", 1, 4, f);
+
+ int2be(version, bytes);
+ fwrite(bytes, 1, 4, f);
+
+ fwrite(cur_digest, 1, 20, f);
+
fwrite(bdatae(buf,""), 1, blength(buf), f);
fclose(f);
@@ -527,18 +552,34 @@ OBJECT cpu_marshal_to_file(STATE, OBJECT obj, char *path, int version) {
return Qtrue;
}
-OBJECT cpu_unmarshal(STATE, uint8_t *str, int version) {
+OBJECT cpu_unmarshal(STATE, uint8_t *str, int len, int version) {
struct marshal_state ms;
OBJECT ret;
+ int in_version;
int offset = 4;
if(!memcmp(str, "RBIS", 4)) {
version = -1;
} else if(!memcmp(str, "RBIX", 4)) {
- if(read_int(str + 4) < version) {
+ in_version = read_int(str + 4);
+ if(in_version < version) {
/* file is out of date. */
return Qnil;
}
+
offset += 4;
+
+ if(in_version == 6) {
+ unsigned char cur_digest[20];
+
+ offset += 20;
+
+ sha1_hash_string((unsigned char*)(str + offset), len - offset, cur_digest);
+
+ /* Check if the calculate one is the one in the stream. */
+ if(memcmp(str + offset - 20, cur_digest, 20)) {
+ return Qnil;
+ }
+ }
} else {
printf("Invalid compiled file.\n");
return Qnil;
@@ -571,7 +612,7 @@ OBJECT cpu_unmarshal_file(STATE, const char *path, int version) {
map = mmap(NULL, (size_t) st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- obj = cpu_unmarshal(state, map, version);
+ obj = cpu_unmarshal(state, map, (int)st.st_size, version);
munmap(map, st.st_size);
return obj;
View
22 shotgun/lib/cpu_task.c
@@ -144,7 +144,7 @@ int cpu_task_select(STATE, cpu c, OBJECT nw) {
memcpy(ct, new_task, sizeof(struct cpu_task));
home = NIL_P(c->home_context) ? c->active_context : c->home_context;
-
+
cpu_restore_context_with_home(state, c, c->active_context, home, FALSE, FALSE);
// printf("Swaping to task %p\t(%lu / %lu / %p / %p / %p)\n", (void*)nw, c->sp, c->ip, cpu_current_method(state, c), c->active_context, c->home_context);
@@ -320,6 +320,26 @@ OBJECT cpu_thread_find_highest(STATE) {
}
}
+void cpu_thread_dequeue(STATE, OBJECT thr) {
+ int i, t;
+ OBJECT lst, tup;
+
+ tup = state->global->scheduled_threads;
+ t = NUM_FIELDS(tup);
+ for(i = 0; i < t; i++) {
+ lst = tuple_at(state, tup, i);
+
+ /* We could exit here, since a thread should only be in one
+ priority list. But run them all for now to be sure. */
+ state->pending_threads -= list_delete(state, lst, thr);
+ }
+}
+
+void cpu_thread_force_run(STATE, cpu c, OBJECT thr) {
+ cpu_thread_dequeue(state, thr);
+ cpu_thread_switch(state, c, thr);
+}
+
void cpu_thread_switch(STATE, cpu c, OBJECT thr) {
OBJECT task;
View
8 shotgun/lib/list.c
@@ -59,17 +59,19 @@ OBJECT list_shift(STATE, OBJECT self) {
return list_node_get_object(node);
}
-void list_delete(STATE, OBJECT self, OBJECT obj) {
+int list_delete(STATE, OBJECT self, OBJECT obj) {
OBJECT node, lst, nxt;
- int count;
+ int count, deleted;
+ deleted = 0;
count = 0;
lst = Qnil;
node = list_get_first(self);
while(!NIL_P(node)) {
nxt = list_node_get_next(node);
if(list_node_get_object(node) == obj) {
+ deleted++;
if(NIL_P(lst)) {
list_set_first(self, nxt);
} else {
@@ -83,4 +85,6 @@ void list_delete(STATE, OBJECT self, OBJECT obj) {
}
list_set_count(self, I2N(count));
+
+ return deleted;
}
View
2 shotgun/lib/list.h
@@ -3,7 +3,7 @@ void Init_list(STATE);
OBJECT list_new(STATE);
void list_append(STATE, OBJECT self, OBJECT obj);
OBJECT list_shift(STATE, OBJECT self);
-void list_delete(STATE, OBJECT self, OBJECT obj);
+int list_delete(STATE, OBJECT self, OBJECT obj);
#define ListFields 3
#define ListNodeFields 2
View
12 shotgun/lib/machine.c
@@ -354,11 +354,13 @@ void _machine_error_reporter(int sig, siginfo_t *info, void *ctx) {
The check for - 8 is because it's common this happens when
trying to grab the class of a non-reference. The class is
8 bytes into the header. */
- addr = (OBJECT)(info->si_addr);
- if(!REFERENCE_P(addr) || !REFERENCE_P(addr - 4) || !REFERENCE_P(addr - 8)) {
- printf("Attempted to access field of non-reference.\n");
- if(g_use_firesuit) {
- machine_handle_fire(FIRE_NULL);
+ if(sig == SIGSEGV || sig == SIGBUS) {
+ addr = (OBJECT)(info->si_addr);
+ if(!REFERENCE_P(addr) || !REFERENCE_P(addr - 4) || !REFERENCE_P(addr - 8)) {
+ printf("Attempted to access field of non-reference.\n");
+ if(g_use_firesuit) {
+ machine_handle_fire(FIRE_NULL);
+ }
}
}
View
6 shotgun/lib/primitives.rb
@@ -1383,7 +1383,7 @@ def unmarshal_object
POP(t1, STRING);
POP(t2, FIXNUM);
- stack_push(cpu_unmarshal(state, (uint8_t*)string_byte_address(state, t1), FIXNUM_TO_INT(t2)));
+ stack_push(cpu_unmarshal(state, (uint8_t*)string_byte_address(state, t1), FIXNUM_TO_INT(string_get_bytes(t1)), FIXNUM_TO_INT(t2)));
CODE
end
@@ -2324,8 +2324,8 @@ def thread_run
self = stack_pop();
/* So when we're restored, there is a ret val. */
stack_push(Qnil);
- cpu_thread_schedule(state, c->current_thread);
- cpu_thread_switch(state, c, self);
+ cpu_thread_schedule(state, c->current_thread);
+ cpu_thread_force_run(state, c, self);
CODE
end
View
232 shotgun/lib/sha1.c
@@ -0,0 +1,232 @@
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/*
+
+Modified by Evan Phoenix to incorporate into Rubinius.
+
+*/
+
+#if !CONFIG_BIG_ENDIAN
+#define LITTLE_ENDIAN 1
+#endif
+
+#define SHA1HANDSOFF /* Copies data before messing with it. */
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include "sha1.h"
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
+{
+unsigned long a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ unsigned long l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned long i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+/* rubinius specific */
+void sha1_hash_bstring(bstring input, unsigned char *digest) {
+ SHA1_CTX context;
+ SHA1Init(&context);
+ SHA1Update(&context, (unsigned char*)bdatae(input,""), blength(input));
+ SHA1Final(digest, &context);
+}
+
+void sha1_hash_string(unsigned char *input, int len, unsigned char *digest) {
+ SHA1_CTX context;
+ SHA1Init(&context);
+ SHA1Update(&context, input, len);
+ SHA1Final(digest, &context);
+}
+
+/*************************************************************/
+
+#if 0
+
+int main(int argc, char** argv)
+{
+int i, j;
+SHA1_CTX context;
+unsigned char digest[20], buffer[16384];
+FILE* file;
+
+ if (argc > 2) {
+ puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>");
+ puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
+ exit(0);
+ }
+ if (argc < 2) {
+ file = stdin;
+ }
+ else {
+ if (!(file = fopen(argv[1], "rb"))) {
+ fputs("Unable to open file.", stderr);
+ exit(-1);
+ }
+ }
+ SHA1Init(&context);
+ while (!feof(file)) { /* note: what if ferror(file) */
+ i = fread(buffer, 1, 16384, file);
+ SHA1Update(&context, buffer, i);
+ }
+ SHA1Final(digest, &context);
+ fclose(file);
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 4; j++) {
+ printf("%02X", digest[i*4+j]);
+ }
+ putchar(' ');
+ }
+ putchar('\n');
+ exit(0);
+}
+
+#endif
View
20 shotgun/lib/sha1.h
@@ -0,0 +1,20 @@
+#ifndef RBS_SHA1_H
+#define RBS_SHA1_H
+
+#include <bstrlib.h>
+
+typedef struct {
+ unsigned long state[5];
+ unsigned long count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+
+void sha1_hash_bstring(bstring input, unsigned char *digest);
+void sha1_hash_string(unsigned char *input, int len, unsigned char *digest);
+
+#endif
View
4 spec/core/kernel/rand_spec.rb
@@ -2,10 +2,6 @@
require File.dirname(__FILE__) + '/fixtures/classes'
describe "Kernel.rand" do
- it "is seeded uniquely at startup" do
- `#{RUBY_NAME} -e "puts rand"`.should_not == `#{RUBY_NAME} -e "puts rand"`
- end
-
it "returns a random float less than 1 if no max argument is passed" do
rand.kind_of?(Float).should == true
end

0 comments on commit 4183197

Please sign in to comment.
Something went wrong with that request. Please try again.