www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - incorrect data when returning static array in place of dynamic

reply "sigod" <sigod.mail gmail.com> writes:
Consider this code:
```
import std.digest.digest;
import std.stdio;

ubyte[] hmac_sha1(const(ubyte)[] key, const(ubyte)[] message)
{
	import std.digest.sha;

	enum block_size = 64;

	if (key.length > block_size)
		key = sha1Of(key);
	if (key.length < block_size)
		key.length = block_size;

	ubyte[] o_key_pad = key.dup;
	ubyte[] i_key_pad = key.dup;

	o_key_pad[] ^= 0x5c;
	i_key_pad[] ^= 0x36;

	sha1Of(o_key_pad ~ sha1Of(i_key_pad ~ 
message)).toHexString.writeln; // prints correct string

	return sha1Of(o_key_pad ~ sha1Of(i_key_pad ~ message));
}

void main()
{
	hmac_sha1(cast(ubyte[])"", cast(ubyte[])"").toHexString.writeln; 
// incorrect
	"---".writeln;
	hmac_sha1(cast(ubyte[])"key", cast(ubyte[])"The quick brown fox 
jumps over the lazy dog").toHexString.writeln;
}
```

prints:
```
FBDB1D1B18AA6C08324B7D64B71FB76370690E1D
0000000018AA6C081400000038FD180010000000
---
DE7C9B85B8B78AA6BC8A7A36F70A90701C9DB4D9
00000000B8B78AA61400000038FD180010000000
```

Why does function return incorrect data? Using `.dup` in return 
expression or using `ubyte[20]` as return type fixes problem, but 
why?
Jul 05 2015
parent reply "thedeemon" <dlang thedeemon.com> writes:
On Sunday, 5 July 2015 at 18:57:46 UTC, sigod wrote:
 Why does function return incorrect data? Using `.dup` in return 
 expression or using `ubyte[20]` as return type fixes problem, 
 but why?
Because sha1Of() returns ubyte[20], this is a stack-allocated array, a value type. If you put correct return type there, it will be returned by value and everything's fine. If your return type is ubyte[] (a reference type), a slice of stack-allocated array is returned which creates a reference to stack data that doesn't exist anymore.
Jul 05 2015
parent reply "sigod" <sigod.mail gmail.com> writes:
On Monday, 6 July 2015 at 05:30:46 UTC, thedeemon wrote:
 On Sunday, 5 July 2015 at 18:57:46 UTC, sigod wrote:
 Why does function return incorrect data? Using `.dup` in 
 return expression or using `ubyte[20]` as return type fixes 
 problem, but why?
Because sha1Of() returns ubyte[20], this is a stack-allocated array, a value type. If you put correct return type there, it will be returned by value and everything's fine. If your return type is ubyte[] (a reference type), a slice of stack-allocated array is returned which creates a reference to stack data that doesn't exist anymore.
Aren't compiler smart enough to prevent it? ``` ubyte[] test1() { auto b = sha1Of(""); return b; // Error: escaping reference to local b } ubyte[] test2() { return sha1Of(""); // works, but returns incorrect data } ``` Looks more like a bug to me.
Jul 06 2015
parent reply "anonymous" <anonymous example.com> writes:
On Monday, 6 July 2015 at 07:48:17 UTC, sigod wrote:
 Aren't compiler smart enough to prevent it?

 ```
 ubyte[] test1()
 {
 	auto b = sha1Of("");

 	return b; // Error: escaping reference to local b
 }

 ubyte[] test2()
 {
 	return sha1Of(""); // works, but returns incorrect data
 }
 ```

 Looks more like a bug to me.
dmd 2.068.0 catches this. You can get the beta here: http://downloads.dlang.org/pre-releases/2.x/2.068.0/
Jul 06 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 6 July 2015 at 10:20:28 UTC, anonymous wrote:
 dmd 2.068.0 catches this. You can get the beta here:
 http://downloads.dlang.org/pre-releases/2.x/2.068.0/
... and it already contains a std.digest.hmac module :-)
Jul 06 2015
parent "sigod" <sigod.mail gmail.com> writes:
On Monday, 6 July 2015 at 14:56:38 UTC, Marc Schütz wrote:
 On Monday, 6 July 2015 at 10:20:28 UTC, anonymous wrote:
 dmd 2.068.0 catches this. You can get the beta here:
 http://downloads.dlang.org/pre-releases/2.x/2.068.0/
... and it already contains a std.digest.hmac module :-)
Yes, thanks. I know that. But I don't really want to use pre-release version on server.
Jul 10 2015
prev sibling parent "sigod" <sigod.mail gmail.com> writes:
On Monday, 6 July 2015 at 10:20:28 UTC, anonymous wrote:
 On Monday, 6 July 2015 at 07:48:17 UTC, sigod wrote:
 Aren't compiler smart enough to prevent it?

 ```
 ubyte[] test1()
 {
 	auto b = sha1Of("");

 	return b; // Error: escaping reference to local b
 }

 ubyte[] test2()
 {
 	return sha1Of(""); // works, but returns incorrect data
 }
 ```

 Looks more like a bug to me.
dmd 2.068.0 catches this. You can get the beta here: http://downloads.dlang.org/pre-releases/2.x/2.068.0/
That's good to know.
Jul 10 2015