Project

General

Profile

Feature #10098 » tsafe_inline.patch

arrtchiu (Matt U), 07/29/2014 10:29 AM

View differences:

configure.in
AC_CHECK_FUNCS(utimes)
AC_CHECK_FUNCS(wait4)
AC_CHECK_FUNCS(waitpid)
AC_CHECK_FUNCS(consttime_memequal)
AC_CHECK_FUNCS(timingsafe_memcmp)
AS_IF([test "$ac_cv_func_getcwd" = yes], [
AC_CACHE_CHECK(if getcwd allocates buffer if NULL is given, [rb_cv_getcwd_malloc],
string.c
return str_eql(str1, str2);
}
static inline VALUE
rb_tsafe_eql(const char* buf1, const char* buf2, long len)
{
#if defined(HAVE_TIMINGSAFE_MEMCMP)
return (timingsafe_memcmp(buf1, buf2, len) == 0);
#elif defined(HAVE_CONSTTIME_MEMEQUAL)
return (consttime_memequal(buf1, buf2, len) != 0);
#else
VALUE result;
long idx;
result = 0;
idx = 0;
if (UNALIGNED_WORD_ACCESS || !((VALUE)buf1 % sizeof(VALUE)) && !((VALUE)buf2 % sizeof(VALUE))) {
for (; idx < len; idx += sizeof(VALUE)) {
result |= *(const VALUE *)(buf1+idx) ^ *(const VALUE *)(buf2+idx);
}
}
for (; idx < len; idx++) {
result |= buf1[idx] ^ buf2[idx];
}
return (result == 0);
#endif
}
/*
* call-seq:
* str.tsafe_eql?(other) -> true or false
*
* Compares each byte of +str+ against +other+, similarly to String#eql?, but
* performs the comparison in constant-time.
*
* This method is timing-safe if both strings are of equal length.
*/
static VALUE
rb_str_tsafe_eql(VALUE str1, VALUE str2)
{
long len;
str2 = StringValue(str2);
len = RSTRING_LEN(str1);
if (RSTRING_LEN(str2) != len) return Qfalse;
if (rb_tsafe_eql(RSTRING_PTR(str1), RSTRING_PTR(str2), len) != 0) return Qtrue;
return Qfalse;
}
/*
* call-seq:
* string <=> other_string -> -1, 0, +1 or nil
......
rb_define_method(rb_cString, "==", rb_str_equal, 1);
rb_define_method(rb_cString, "===", rb_str_equal, 1);
rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
rb_define_method(rb_cString, "tsafe_eql?", rb_str_tsafe_eql, 1);
rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
rb_define_method(rb_cString, "+", rb_str_plus, 1);
test/ruby/test_string.rb
casetest(S("CaT"), S('cAt'), true) # find these in the case.
end
def test_TIMING_SAFE_EQUAL # 'tsafe_eql?'
assert_equal(true, S("foo").tsafe_eql?(S("foo")))
assert_equal(false, S("foo").tsafe_eql?(S("foO")))
assert_equal(true, S("f\x00oo").tsafe_eql?(S("f\x00oo")))
assert_equal(false, S("f\x00oo").tsafe_eql?(S("f\x00oO")))
end
def test_capitalize
assert_equal(S("Hello"), S("hello").capitalize)
assert_equal(S("Hello"), S("hELLO").capitalize)
(4-4/5)