[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#663520: marked as done (Support for incremental updates, bigarrays and multithreading)



Your message dated Sun, 03 Nov 2013 16:48:42 +0000
with message-id <E1Vd0qw-0001m2-MY@franck.debian.org>
and subject line Bug#663520: fixed in ocaml-sha 1.9-1
has caused the Debian Bug report #663520,
regarding Support for incremental updates, bigarrays and multithreading
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
663520: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=663520
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Source: ocaml-sha
Version: 1.7-2
Severity: wishlist
Tags: upstream patch

Hi,

I'm afraid I combined a few things in a single patch. If needed I can
split it up into smaller chunks:

- Expose the context
  + Add type ctx
  + Expose init, update and finalize
- Add context copy function
- Rename update to unsafe_update_substring
- Add update_substring with range checking
- Add update_string
- Add bigarray support
  + Add type buf (shortcut because the full type is too long to type)
  + Add update_buffer
  + Add buffer
- Change stub_sha1_file() to release/aquire the runtime system

For me the important functions are buffer to compute the sha checksum
in a thread and init + update_buffer + finalize to do the same if the
data is split up into multiple blocks.

Since strings can be moved by the GC the string based functions can
not release the runtime system and therefore can not run concurrently
with other threads. Some simple tests with bigarrays show a speedup of
3.7 times on 4 cores even with smallish blocks.

MfG
	Goswin

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.1.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=C, LC_CTYPE=de_DE (charmap=ISO-8859-1)
Shell: /bin/sh linked to /bin/dash
Description: Support for update and bigarray
 This patch exposes the context and provides incremental update
 functions for strings and bigarrays. The bigarray functions run
 without holding the global lock and the file function is also changed
 to run without the global lock. This enables other threads to run
 concurrently while the sha checksum is being computed.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-11

---

Index: ocaml-sha-1.7/sha1_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha1_stubs.c	2012-03-11 22:29:16.000000000 +0100
+++ ocaml-sha-1.7/sha1_stubs.c	2012-03-11 22:39:21.000000000 +0100
@@ -25,7 +25,7 @@
 	int fd; ssize_t n;
 	struct sha1_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha1_init(&ctx);
@@ -44,6 +44,8 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha1_ctx *) a)
 
@@ -68,6 +70,19 @@
 	CAMLreturn(Val_unit);
 }
 
+CAMLprim value stub_sha1_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha1_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
+
 CAMLprim value stub_sha1_finalize(value ctx)
 {
 	CAMLparam1(ctx);
@@ -79,14 +94,34 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha1_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha1_ctx), Abstract_tag);
+	sha1_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 CAMLprim value stub_sha1_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdup(String_val(name));
+	sha1_digest digest;
+
+	caml_release_runtime_system();
+	if (sha1_file(name_dup, &digest)) {
+	    free(name_dup);
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha1_digest), Abstract_tag);
-	if (sha1_file(String_val(name), (sha1_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha1_digest *)result, &digest, sizeof(sha1_digest));
 
 	CAMLreturn(result);
 }
Index: ocaml-sha-1.7/sha1.mli
===================================================================
--- ocaml-sha-1.7.orig/sha1.mli	2012-03-11 22:29:16.000000000 +0100
+++ ocaml-sha-1.7/sha1.mli	2012-03-11 22:49:00.000000000 +0100
@@ -14,12 +14,44 @@
 
 (** SHA1 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha1_init"
+
+(** Sha1.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+
+(** Sha1.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha1.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
+
+(** Sha1.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha1_update_bigarray"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha1_finalize"
+
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha1_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
@@ -27,6 +59,9 @@
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha1.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha1.channel ic
Index: ocaml-sha-1.7/sha1.ml
===================================================================
--- ocaml-sha-1.7.orig/sha1.ml	2012-03-11 22:29:16.000000000 +0100
+++ ocaml-sha-1.7/sha1.ml	2012-03-11 22:49:37.000000000 +0100
@@ -14,11 +14,14 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha1_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha1_update_bigarray"
 external finalize: ctx -> t = "stub_sha1_finalize"
+external copy : ctx -> ctx = "stub_sha1_copy"
 external to_bin: t -> string = "stub_sha1_to_bin"
 external to_hex: t -> string = "stub_sha1_to_hex"
 external file_fast: string -> t = "stub_sha1_file"
@@ -28,16 +31,29 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
+	finalize ctx
+
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
 	finalize ctx
 
 let channel chan len =
@@ -52,7 +68,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Index: ocaml-sha-1.7/sha1.c
===================================================================
--- ocaml-sha-1.7.orig/sha1.c	2012-03-11 22:29:16.000000000 +0100
+++ ocaml-sha-1.7/sha1.c	2012-03-11 22:29:29.000000000 +0100
@@ -33,6 +33,14 @@
 	ctx->h[4] = 0xC3D2E1F0;
 }
 
+/**
+ * sha1_copy - Copy SHA1 context
+ */
+void sha1_copy(struct sha1_ctx *dst, struct sha1_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 #define f1(x, y, z)   (z ^ (x & (y ^ z)))         /* x ? y : z */
 #define f2(x, y, z)   (x ^ y ^ z)                 /* XOR */
 #define f3(x, y, z)   ((x & y) + (z & (x ^ y)))   /* majority */
Index: ocaml-sha-1.7/sha1.h
===================================================================
--- ocaml-sha-1.7.orig/sha1.h	2012-03-11 22:29:16.000000000 +0100
+++ ocaml-sha-1.7/sha1.h	2012-03-11 22:29:29.000000000 +0100
@@ -25,6 +25,7 @@
 typedef struct { unsigned int digest[5]; } sha1_digest;
 
 void sha1_init(struct sha1_ctx *ctx);
+void sha1_copy(struct sha1_ctx *dst, struct sha1_ctx *src);
 void sha1_update(struct sha1_ctx *ctx, unsigned char *data, int len);
 void sha1_finalize(struct sha1_ctx *ctx, sha1_digest *out);
 void sha1_to_bin(sha1_digest *digest, char *out);
Index: ocaml-sha-1.7/sha256_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha256_stubs.c	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha256_stubs.c	2012-03-11 22:39:38.000000000 +0100
@@ -25,7 +25,7 @@
 	int fd; ssize_t n;
 	struct sha256_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha256_init(&ctx);
@@ -44,6 +44,8 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha256_ctx *) a)
 
@@ -67,6 +69,19 @@
 	CAMLreturn(Val_unit);
 }
 
+CAMLprim value stub_sha256_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha256_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
+
 CAMLprim value stub_sha256_finalize(value ctx)
 {
 	CAMLparam1(ctx);
@@ -78,14 +93,34 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha256_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha256_ctx), Abstract_tag);
+	sha256_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 CAMLprim value stub_sha256_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdup(String_val(name));
+	sha256_digest digest;
+
+	caml_release_runtime_system();
+	if (sha256_file(name_dup, &digest)) {
+	    free(name_dup);
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha256_digest), Abstract_tag);
-	if (sha256_file(String_val(name), (sha256_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha256_digest *)result, &digest, sizeof(sha256_digest));
 
 	CAMLreturn(result);
 }
Index: ocaml-sha-1.7/sha256.mli
===================================================================
--- ocaml-sha-1.7.orig/sha256.mli	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha256.mli	2012-03-11 22:50:18.000000000 +0100
@@ -14,12 +14,44 @@
 
 (** SHA256 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha256_init"
+
+(** Sha256.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+
+(** Sha256.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha256.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
+
+(** Sha256.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha256_update_bigarray"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha256_finalize"
+
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha256_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
@@ -27,6 +59,9 @@
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha256.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha256.channel ic
Index: ocaml-sha-1.7/sha256.ml
===================================================================
--- ocaml-sha-1.7.orig/sha256.ml	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha256.ml	2012-03-11 22:49:52.000000000 +0100
@@ -14,11 +14,14 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha256_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha256_update_bigarray"
 external finalize: ctx -> t = "stub_sha256_finalize"
+external copy : ctx -> ctx = "stub_sha256_copy"
 external to_bin: t -> string = "stub_sha256_to_bin"
 external to_hex: t -> string = "stub_sha256_to_hex"
 external file_fast: string -> t = "stub_sha256_file"
@@ -28,16 +31,29 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
+	finalize ctx
+
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
 	finalize ctx
 
 let channel chan len =
@@ -52,7 +68,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Index: ocaml-sha-1.7/sha256.c
===================================================================
--- ocaml-sha-1.7.orig/sha256.c	2012-03-09 07:53:01.000000000 +0100
+++ ocaml-sha-1.7/sha256.c	2012-03-11 22:30:11.000000000 +0100
@@ -36,6 +36,14 @@
 	ctx->h[7] = 0x5be0cd19;
 }
 
+/**
+ * sha256_copy - Copy SHA256 context
+ */
+void sha256_copy(struct sha256_ctx *dst, struct sha256_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 /* 232 times the cube root of the first 64 primes 2..311 */
 static const unsigned int k[] = {
 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
Index: ocaml-sha-1.7/sha256.h
===================================================================
--- ocaml-sha-1.7.orig/sha256.h	2009-11-09 12:09:21.000000000 +0100
+++ ocaml-sha-1.7/sha256.h	2012-03-11 22:29:29.000000000 +0100
@@ -25,6 +25,7 @@
 typedef struct { unsigned int digest[8]; } sha256_digest;
 
 void sha256_init(struct sha256_ctx *ctx);
+void sha256_copy(struct sha256_ctx *dst, struct sha256_ctx *src);
 void sha256_update(struct sha256_ctx *ctx, unsigned char *data, int len);
 void sha256_finalize(struct sha256_ctx *ctx, sha256_digest *out);
 void sha256_to_bin(sha256_digest *digest, char *out);
Index: ocaml-sha-1.7/sha512_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha512_stubs.c	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha512_stubs.c	2012-03-11 22:39:50.000000000 +0100
@@ -25,7 +25,7 @@
 	int fd; ssize_t n;
 	struct sha512_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha512_init(&ctx);
@@ -44,6 +44,8 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha512_ctx *) a)
 
@@ -67,6 +69,19 @@
 	CAMLreturn(Val_unit);
 }
 
+CAMLprim value stub_sha512_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha512_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
+
 CAMLprim value stub_sha512_finalize(value ctx)
 {
 	CAMLparam1(ctx);
@@ -78,14 +93,34 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha512_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha512_ctx), Abstract_tag);
+	sha512_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 CAMLprim value stub_sha512_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdup(String_val(name));
+	sha512_digest digest;
+
+	caml_release_runtime_system();
+	if (sha512_file(name_dup, &digest)) {
+	    free(name_dup);
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha512_digest), Abstract_tag);
-	if (sha512_file(String_val(name), (sha512_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha512_digest *)result, &digest, sizeof(sha512_digest));
 
 	CAMLreturn(result);
 }
Index: ocaml-sha-1.7/sha512.mli
===================================================================
--- ocaml-sha-1.7.orig/sha512.mli	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha512.mli	2012-03-11 22:50:28.000000000 +0100
@@ -14,12 +14,44 @@
 
 (** SHA512 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha512_init"
+
+(** Sha512.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+
+(** Sha512.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha512.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
+
+(** Sha512.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha512_update_bigarray"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha512_finalize"
+
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha512_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
@@ -27,6 +59,9 @@
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha512.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha512.channel ic
Index: ocaml-sha-1.7/sha512.ml
===================================================================
--- ocaml-sha-1.7.orig/sha512.ml	2012-03-11 20:56:00.000000000 +0100
+++ ocaml-sha-1.7/sha512.ml	2012-03-11 22:50:01.000000000 +0100
@@ -14,11 +14,14 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha512_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha512_update_bigarray"
 external finalize: ctx -> t = "stub_sha512_finalize"
+external copy : ctx -> ctx = "stub_sha512_copy"
 external to_bin: t -> string = "stub_sha512_to_bin"
 external to_hex: t -> string = "stub_sha512_to_hex"
 external file_fast: string -> t = "stub_sha512_file"
@@ -28,16 +31,29 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
+	finalize ctx
+
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
 	finalize ctx
 
 let channel chan len =
@@ -52,7 +68,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Index: ocaml-sha-1.7/sha512.c
===================================================================
--- ocaml-sha-1.7.orig/sha512.c	2009-11-09 12:09:21.000000000 +0100
+++ ocaml-sha-1.7/sha512.c	2012-03-11 22:30:48.000000000 +0100
@@ -35,6 +35,14 @@
 	ctx->h[7] = 0x5be0cd19137e2179ULL;
 }
 
+/**
+ * sha512_copy - Copy SHA512 context
+ */
+void sha512_copy(struct sha512_ctx *dst, struct sha512_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 /* 232 times the cube root of the first 64 primes 2..311 */
 static const uint64_t k[] = {
 	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
Index: ocaml-sha-1.7/sha512.h
===================================================================
--- ocaml-sha-1.7.orig/sha512.h	2009-11-09 12:09:21.000000000 +0100
+++ ocaml-sha-1.7/sha512.h	2012-03-11 22:29:29.000000000 +0100
@@ -27,6 +27,7 @@
 typedef struct { uint64_t digest[8]; } sha512_digest;
 
 void sha512_init(struct sha512_ctx *ctx);
+void sha512_copy(struct sha512_ctx *dst, struct sha512_ctx *src);
 void sha512_update(struct sha512_ctx *ctx, unsigned char *data, int len);
 void sha512_finalize(struct sha512_ctx *ctx, sha512_digest *out);
 void sha512_to_bin(sha512_digest *digest, char *out);

--- End Message ---
--- Begin Message ---
Source: ocaml-sha
Source-Version: 1.9-1

We believe that the bug you reported is fixed in the latest version of
ocaml-sha, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 663520@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Eric Cooper <ecc@cmu.edu> (supplier of updated ocaml-sha package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.8
Date: Fri, 01 Nov 2013 20:05:22 -0400
Source: ocaml-sha
Binary: libsha-ocaml libsha-ocaml-dev
Architecture: source amd64
Version: 1.9-1
Distribution: unstable
Urgency: low
Maintainer: Debian OCaml Maintainers <debian-ocaml-maint@lists.debian.org>
Changed-By: Eric Cooper <ecc@cmu.edu>
Description: 
 libsha-ocaml - SHA cryptographic hash functions for OCaml (runtime)
 libsha-ocaml-dev - SHA cryptographic hash functions for OCaml (development files)
Closes: 663520
Changes: 
 ocaml-sha (1.9-1) unstable; urgency=low
 .
   * New upstream version (closes: #663520)
   * Patch C stubs to silence gcc warnings
   * Update standards version and build dependencies
   * Drop DM-Upload-Allowed
   * Update copyright format
   * Update Homepage and VCS-* fields
   * Increased debhelper compatibility level to 9
   * Update watch file for github
Checksums-Sha1: 
 fe77a029671a81f54b6e6cc212019459086a54e5 1379 ocaml-sha_1.9-1.dsc
 740eefab3e316fe9cb86a68a4bcbe1a8e8de828a 12872 ocaml-sha_1.9.orig.tar.gz
 eeb701e5f244c71a64753b99aedd21b56234a183 4813 ocaml-sha_1.9-1.debian.tar.gz
 b309b46d7dbecb0d103e966162a8dbec9ad5e40f 19740 libsha-ocaml_1.9-1_amd64.deb
 c1fb6de836f4e11c3460a773cf3144bb1e269214 28242 libsha-ocaml-dev_1.9-1_amd64.deb
Checksums-Sha256: 
 8118d7a54551244a7033f04ee3e241430d33ffda9b49b706c5e1a354ca0b3b82 1379 ocaml-sha_1.9-1.dsc
 caa1dd9071c2c56ca180061bb8e1824ac3b5e83de8ec4ed197275006c2a088d0 12872 ocaml-sha_1.9.orig.tar.gz
 1562ac01e6332c6f37c6dd265295261f2415f9f0e5e7e937c943b85e2ab0cdf3 4813 ocaml-sha_1.9-1.debian.tar.gz
 87171341658913c499c5fafe7a6530e6a665cc4011c2ca25e043d735c6e18b6b 19740 libsha-ocaml_1.9-1_amd64.deb
 245d773a4b1ca89ca8d78c887c7dcc1191e11d3881d425c38473491c7f0ef03b 28242 libsha-ocaml-dev_1.9-1_amd64.deb
Files: 
 aeb2509f07ef2274ed4209c66ec4d9ec 1379 ocaml optional ocaml-sha_1.9-1.dsc
 b15756c7efed004acc80a93778920178 12872 ocaml optional ocaml-sha_1.9.orig.tar.gz
 e6bda343f4d425de4b6d08a37a3ee1d6 4813 ocaml optional ocaml-sha_1.9-1.debian.tar.gz
 1f35ad7e425d9b6e81a0526dba30ace1 19740 ocaml optional libsha-ocaml_1.9-1_amd64.deb
 a2f2cf8d343e0f3aed9349b983e114ce 28242 ocaml optional libsha-ocaml-dev_1.9-1_amd64.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.15 (GNU/Linux)

iEYEARECAAYFAlJ1LR8ACgkQ99kx1LiC69dLuACeKKePOOJ4f1UnwG38dobuwrQA
/DQAn1F9jkceFyl997XNmdcOvZp/bFrS
=odES
-----END PGP SIGNATURE-----

--- End Message ---

Reply to: