asn1tools icon indicating copy to clipboard operation
asn1tools copied to clipboard

Error "SEQUENCE OF has no maximum length." when has maximum length

Open sargun opened this issue 4 years ago • 4 comments

My ASN.1 file is as follows:


OCI2 DEFINITIONS ::=
BEGIN

Blake3hash ::= OCTET STRING (SIZE(32))

Version ::= INTEGER {
	v1(0)
}

-- Nanoseconds since Epoch
Timestamp ::= INTEGER (0..MAX)

File ::= SEQUENCE {
	contents	[0] Blake3hash OPTIONAL,
	mode		[1] BIT STRING {
						rusr	(0),
						wusr	(1),
						xusr	(2),
						rgrp	(3),
						wgrp	(4),
						xgrp	(5),
						roth	(6),
						woth	(7),
						xoth	(8),
						suid	(9),
						sgid	(10),
						svtx	(11)
					},
	uid			[2] INTEGER (0..MAX),
	gid			[3] INTEGER (0..MAX),
	atime		[4] Timestamp OPTIONAL,
	btime		[5] Timestamp OPTIONAL,
	ctime		[6] Timestamp OPTIONAL,
	mtime		[7] Timestamp OPTIONAL
}

Children ::= CHOICE {
	nodes	[0] SEQUENCE OF Node (SIZE(0..256)),
	hashes	[1] SEQUENCE OF Blake3hash (SIZE(0..256))
}

Node ::= SEQUENCE {
	prefix	[0] UTF8String (SIZE(1..4096)),
	file	[1] File OPTIONAL,
	nodes	[2] Children
}

Root ::= SEQUENCE {
	version	[0] Version DEFAULT v1,
	child	[1] CHOICE {
		node	Node,
		hash	Blake3hash
	}
}
END

I get the error:

$ asn1tools generate_c_source hello.asn1 
error: OCI2.Children.nodes: SEQUENCE OF has no maximum length.

Is this due to the recursion nature of the data structure?

sargun avatar Dec 29 '20 12:12 sargun

Hi Sargun,

you have a minor issue in the definition of your SEQUENCE OF. The size of an array is indicated after SEQUENCE, not after the array item type.

So change

Children ::= CHOICE {
	nodes	[0] SEQUENCE OF Node (SIZE(0..256)),
	hashes	[1] SEQUENCE OF Blake3hash (SIZE(0..256))

}

to

Children ::= CHOICE {
	nodes	[0] SEQUENCE (SIZE(0..256)) OF Node,
	hashes	[1] SEQUENCE (SIZE(0..256)) OF Blake3hash
}

and you should be fine.

Futsch1 avatar Dec 29 '20 12:12 Futsch1

Thanks, but now I'm running into the recursion problem. I just saw in the docs:

Recursive types are not supported.

Is there any ways to work around this, or is there a way to limit recursion in the spec?

See error:

(venv) sargun:oci2 sargun$ asn1tools generate_c_source --namespace oer --generate-fuzzer -f hello.asn1 
error: maximum recursion depth exceeded in comparison

Spec:

OCI2 DEFINITIONS ::=
BEGIN

Blake3hash ::= OCTET STRING (SIZE(32))

Version ::= INTEGER {
	v1(0)
} (0..18446744073709551615)

-- Nanoseconds since Epoch
Timestamp ::= SEQUENCE {
	seconds	[0] INTEGER (0..18446744073709551615),
	nsec	[1] INTEGER (0..18446744073709551615)
}

File ::= SEQUENCE {
	contents	[0] Blake3hash OPTIONAL,
	mode		[1] BIT STRING {
						rusr	(0),
						wusr	(1),
						xusr	(2),
						rgrp	(3),
						wgrp	(4),
						xgrp	(5),
						roth	(6),
						woth	(7),
						xoth	(8),
						suid	(9),
						sgid	(10),
						svtx	(11)
					} (SIZE(24)),
	uid			[2] INTEGER (0..18446744073709551615),
	gid			[3] INTEGER (0..18446744073709551615),
	atime		[4] Timestamp OPTIONAL,
	btime		[5] Timestamp OPTIONAL,
	ctime		[6] Timestamp OPTIONAL,
	mtime		[7] Timestamp OPTIONAL
}

Children ::= CHOICE {
	nodes	[0] SEQUENCE (SIZE(0..256)) OF Node,
	hashes	[1] SEQUENCE (SIZE(0..256)) OF Blake3hash
}

-- TODO: Use UTF8 strings here
Node ::= SEQUENCE {
	prefix	[0] OCTET STRING (SIZE(1..4096)),
	file	[1] File OPTIONAL,
	nodes	[2] Children
}

Root ::= SEQUENCE {
	version	[0] Version DEFAULT v1,
	child	[1] CHOICE {
		node	Node,
		hash	Blake3hash
	}
}
END

sargun avatar Dec 29 '20 12:12 sargun

Unfortunately, it is not possible to declare recursive structures in C when not using pointers (which is the case in the C code generator since it avoids dynamic memory usage).

What you can do is declare each level of recursion explicitly by defining a dedicated type for each level, so do something like this:


Children1 ::= CHOICE {
	nodes	[0] SEQUENCE (SIZE(0..256)) OF Node2,
	hashes	[1] SEQUENCE (SIZE(0..256)) OF Blake3hash
}

Children2 ::= SEQUENCE (SIZE(0..256)) OF Blake3hash

Node1 ::= SEQUENCE {
	prefix	[0] OCTET STRING (SIZE(1..4096)),
	file	[1] File OPTIONAL,
	nodes	[2] Children1
}

Node2 ::= SEQUENCE {
	prefix	[0] OCTET STRING (SIZE(1..4096)),
	file	[1] File OPTIONAL,
	nodes	[2] Children2
}

Root ::= SEQUENCE {
	version	[0] Version DEFAULT v1,
	child	[1] CHOICE {
		node	Node1,
		hash	Blake3hash
	}
}

I know that this results in ugly copy-pasta, but it will work.

Futsch1 avatar Dec 29 '20 13:12 Futsch1

It's lots of work, but I recently designed pbtools which generates C code for Google Protocol Buffers. It supports recursive schemas. The same design could be applied to the asn1tools C code generator, but as said, it's a ton of work.

eerimoq avatar Dec 29 '20 13:12 eerimoq