Thread overview
incorrect data when returning static array in place of dynamic
Jul 05, 2015
sigod
Jul 06, 2015
thedeemon
Jul 06, 2015
sigod
Jul 06, 2015
anonymous
Jul 06, 2015
Marc Schütz
Jul 10, 2015
sigod
Jul 10, 2015
sigod
July 05, 2015
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?

July 06, 2015
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.
July 06, 2015
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.
July 06, 2015
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/
July 06, 2015
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 :-)
July 10, 2015
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.
July 10, 2015
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.