Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Refactor PackFile_unpack #86

Merged
3 commits merged into from

1 participant

Commits on Jan 1, 2011
  1. @aantn
  2. @aantn

    Update exception strings in PackFile_Header_validate

    aantn authored
    They now use the correct function name
Commits on Jan 2, 2011
  1. @aantn
This page is out of date. Refresh to see the latest.
Showing with 189 additions and 71 deletions.
  1. +41 −0 include/parrot/packfile.h
  2. +148 −71 src/packfile/api.c
View
41 include/parrot/packfile.h
@@ -713,6 +713,36 @@ void PackFile_funcs_register(SHIM_INTERP,
FUNC_MODIFIES(*pf);
PARROT_EXPORT
+PARROT_WARN_UNUSED_RESULT
+void PackFile_Header_read_uuid(PARROT_INTERP,
+ ARGMOD(PackFile_Header *self),
+ ARGIN(const opcode_t *packed),
+ size_t packed_size)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3)
+ FUNC_MODIFIES(*self);
+
+PARROT_EXPORT
+PARROT_WARN_UNUSED_RESULT
+int PackFile_Header_unpack(PARROT_INTERP,
+ ARGMOD(PackFile_Header *self),
+ ARGIN(const opcode_t *packed),
+ size_t packed_size,
+ INTVAL pf_options)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3)
+ FUNC_MODIFIES(*self);
+
+PARROT_EXPORT
+void PackFile_Header_validate(PARROT_INTERP,
+ ARGIN(const PackFile_Header *self),
+ INTVAL pf_options)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+PARROT_EXPORT
INTVAL PackFile_map_segments(PARROT_INTERP,
ARGIN(const PackFile_Directory *dir),
PackFile_map_segments_func_t callback,
@@ -948,6 +978,17 @@ void Parrot_trace_eprintf(ARGIN(const char *s), ...)
PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_PackFile_funcs_register __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(pf))
+#define ASSERT_ARGS_PackFile_Header_read_uuid __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(self) \
+ , PARROT_ASSERT_ARG(packed))
+#define ASSERT_ARGS_PackFile_Header_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(self) \
+ , PARROT_ASSERT_ARG(packed))
+#define ASSERT_ARGS_PackFile_Header_validate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_PackFile_map_segments __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(dir))
View
219 src/packfile/api.c
@@ -673,55 +673,30 @@ mark_const_subs(PARROT_INTERP)
}
-
-
-
/*
-=item C<opcode_t PackFile_unpack(PARROT_INTERP, PackFile *self, const opcode_t
-*packed, size_t packed_size)>
+=item C<void PackFile_Header_validate(PARROT_INTERP, const PackFile_Header
+*self, INTVAL pf_options)>
-Unpacks a C<PackFile> from a block of memory, ensuring that the magic number is
-valid and that Parrot can read this bytecode version, Parrot, and performing
-any required endian and word size transforms.
-
-Returns size of unpacked opcodes if everything is okay, else zero (0).
+Validates a C<PackFile_Header>, ensuring that the magic number is valid and
+that Parrot can read this bytecode version.
+Raises an exception if the header doesn't validate.
=cut
*/
PARROT_EXPORT
-PARROT_WARN_UNUSED_RESULT
-opcode_t
-PackFile_unpack(PARROT_INTERP, ARGMOD(PackFile *self),
- ARGIN(const opcode_t *packed), size_t packed_size)
+void
+PackFile_Header_validate(PARROT_INTERP, ARGIN(const PackFile_Header *self),
+ INTVAL pf_options)
{
- ASSERT_ARGS(PackFile_unpack)
- PackFile_Header * const header = self->header;
- const opcode_t *cursor;
- int header_read_length;
- opcode_t padding;
-#if TRACE_PACKFILE
- PackFile * const pf = self;
-#endif
-
- if (packed_size < PACKFILE_HEADER_BYTES) {
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Buffer length %d is shorter than PACKFILE_HEADER_BYTES %d.",
- packed_size, PACKFILE_HEADER_BYTES);
- }
-
- self->src = packed;
- self->size = packed_size;
-
- /* Extract the header. */
- memcpy(header, packed, PACKFILE_HEADER_BYTES);
+ ASSERT_ARGS(PackFile_Header_validate)
/* Ensure the magic is correct. */
- if (memcmp(header->magic, "\376PBC\r\n\032\n", 8) != 0) {
+ if (memcmp(self->magic, "\376PBC\r\n\032\n", 8) != 0) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: This is not a valid Parrot bytecode file.");
+ "PackFile_Header_validate: This is not a valid Parrot bytecode file.");
}
/* Ensure the bytecode version is one we can read. Currently, we only
@@ -730,74 +705,176 @@ PackFile_unpack(PARROT_INTERP, ARGMOD(PackFile *self),
* tools/dev/pbc_header.pl --upd t/native_pbc/(ASTERISK).pbc
* stamps version and fingerprint in the native tests.
* NOTE: (ASTERISK) is *, we don't want to fool the C preprocessor. */
- if (header->bc_major != PARROT_PBC_MAJOR
- || header->bc_minor != PARROT_PBC_MINOR) {
- if (!(self->options & PFOPT_UTILS))
+ if (self->bc_major != PARROT_PBC_MAJOR
+ || self->bc_minor != PARROT_PBC_MINOR) {
+ if (!(pf_options & PFOPT_UTILS))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PARROT_USAGE_ERROR,
- "PackFile_unpack: This Parrot cannot read bytecode "
+ "PackFile_Header_validate: This Parrot cannot read bytecode "
"files with version %d.%d.",
- header->bc_major, header->bc_minor);
+ self->bc_major, self->bc_minor);
}
/* Check wordsize, byte order and floating point number type are valid. */
- if (header->wordsize != 4 && header->wordsize != 8) {
+ if (self->wordsize != 4 && self->wordsize != 8) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Invalid wordsize %d\n", header->wordsize);
+ "PackFile_Header_validate: Invalid wordsize %d\n", self->wordsize);
}
- if (header->byteorder != 0 && header->byteorder != 1) {
+ if (self->byteorder != 0 && self->byteorder != 1) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Invalid byte ordering %d\n", header->byteorder);
+ "PackFile_Header_validate: Invalid byte ordering %d\n", self->byteorder);
}
- if (header->floattype > FLOATTYPE_MAX) {
+ if (self->floattype > FLOATTYPE_MAX) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Invalid floattype %d\n", header->floattype);
+ "PackFile_Header_validate: Invalid floattype %d\n", self->floattype);
}
+}
- /* Describe what was read for debugging. */
- TRACE_PRINTF(("PackFile_unpack: Wordsize %d.\n", header->wordsize));
- TRACE_PRINTF(("PackFile_unpack: Floattype %d (%s).\n",
- header->floattype,
- header->floattype == FLOATTYPE_8
- ? FLOATTYPE_8_NAME
- : header->floattype == FLOATTYPE_16
- ? FLOATTYPE_16_NAME
- : FLOATTYPE_12_NAME));
- TRACE_PRINTF(("PackFile_unpack: Byteorder %d (%sendian).\n",
- header->byteorder, header->byteorder ? "big " : "little-"));
+
+/*
+
+=item C<void PackFile_Header_read_uuid(PARROT_INTERP, PackFile_Header *self,
+const opcode_t *packed, size_t packed_size)>
+
+Reads a C<PackFile_Header>'s UUID from a block of memory and verifies that it is valid.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_WARN_UNUSED_RESULT
+void
+PackFile_Header_read_uuid(PARROT_INTERP, ARGMOD(PackFile_Header *self),
+ ARGIN(const opcode_t *packed), size_t packed_size)
+{
+ ASSERT_ARGS(PackFile_Header_read_uuid)
/* Check the UUID type is valid and, if needed, read a UUID. */
- if (header->uuid_type == 0) {
+ if (self->uuid_type == 0) {
/* No UUID; fine, nothing more to do. */
}
- else if (header->uuid_type == 1) {
- if (packed_size < (size_t) PACKFILE_HEADER_BYTES + header->uuid_size) {
+ else if (self->uuid_type == 1) {
+ if (packed_size < (size_t) PACKFILE_HEADER_BYTES + self->uuid_size) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Buffer length %d is shorter than PACKFILE_HEADER_BYTES "
- "+ uuid_size %d\n", packed_size, PACKFILE_HEADER_BYTES + header->uuid_size);
+ "PackFile_Header_read_uuid: Buffer length %d is shorter than PACKFILE_HEADER_BYTES "
+ "+ uuid_size %d\n", packed_size, PACKFILE_HEADER_BYTES + self->uuid_size);
}
-
/* Read in the UUID. We'll put it in a NULL-terminated string, just in
* case people use it that way. */
- header->uuid_data = mem_gc_allocate_n_typed(interp,
- header->uuid_size + 1, unsigned char);
+ self->uuid_data = mem_gc_allocate_n_typed(interp,
+ self->uuid_size + 1, unsigned char);
- memcpy(header->uuid_data, packed + PACKFILE_HEADER_BYTES,
- header->uuid_size);
+ memcpy(self->uuid_data, packed + PACKFILE_HEADER_BYTES,
+ self->uuid_size);
/* NULL terminate */
- header->uuid_data[header->uuid_size] = '\0';
+ self->uuid_data[self->uuid_size] = '\0';
}
else
/* Don't know this UUID type. */
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
- "PackFile_unpack: Invalid UUID type %d\n", header->uuid_type);
+ "PackFile_unpack: Invalid UUID type %d\n", self->uuid_type);
+}
+
+
+/*
+
+=item C<int PackFile_Header_unpack(PARROT_INTERP, PackFile_Header *self, const
+opcode_t *packed, size_t packed_size, INTVAL pf_options)>
+
+Unpacks a C<PackFile_Header> from a block of memory and perform some validation
+to check that the head is correct.
+
+Returns size of unpacked header.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_WARN_UNUSED_RESULT
+int
+PackFile_Header_unpack(PARROT_INTERP, ARGMOD(PackFile_Header *self),
+ ARGIN(const opcode_t *packed), size_t packed_size,
+ INTVAL pf_options)
+{
+ ASSERT_ARGS(PackFile_Header_unpack)
+
+ /* Verify that the packfile isn't too small to contain a proper header */
+ if (packed_size < PACKFILE_HEADER_BYTES) {
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
+ "PackFile_unpack: Buffer length %d is shorter than PACKFILE_HEADER_BYTES %d.",
+ packed_size, PACKFILE_HEADER_BYTES);
+ }
+
+ /* Extract the header. */
+ memcpy(self, packed, PACKFILE_HEADER_BYTES);
+
+ /* Validate the header. */
+ PackFile_Header_validate(interp, self, pf_options);
+
+ /* Extract the header's UUID. */
+ PackFile_Header_read_uuid(interp, self, packed, packed_size)
+
+ /* Describe what was read for debugging. */
+ TRACE_PRINTF(("PackFile_Header_unpack: Wordsize %d.\n", self->wordsize));
+ TRACE_PRINTF(("PackFile_Header_unpack: Floattype %d (%s).\n",
+ self->floattype,
+ self->floattype == FLOATTYPE_8
+ ? FLOATTYPE_8_NAME
+ : self->floattype == FLOATTYPE_16
+ ? FLOATTYPE_16_NAME
+ : FLOATTYPE_12_NAME));
+ TRACE_PRINTF(("PackFile_Header_unpack: Byteorder %d (%sendian).\n",
+ self->byteorder, self->byteorder ? "big " : "little-"));
+
+ /* Return the number of bytes in the header */
+ return PACKFILE_HEADER_BYTES + self->uuid_size;
+}
+
+
+/*
+
+=item C<opcode_t PackFile_unpack(PARROT_INTERP, PackFile *self, const opcode_t
+*packed, size_t packed_size)>
+
+Unpacks a C<PackFile> from a block of memory, ensuring that the magic number is
+valid and that Parrot can read this bytecode version, Parrot, and performing
+any required endian and word size transforms.
+
+Returns size of unpacked opcodes if everything is okay, else zero (0).
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_WARN_UNUSED_RESULT
+opcode_t
+PackFile_unpack(PARROT_INTERP, ARGMOD(PackFile *self),
+ ARGIN(const opcode_t *packed), size_t packed_size)
+{
+ ASSERT_ARGS(PackFile_unpack)
+ PackFile_Header * const header = self->header;
+ const opcode_t *cursor;
+ int header_read_length;
+ opcode_t padding;
+#if TRACE_PACKFILE
+ PackFile * const pf = self;
+#endif
+
+ self->src = packed;
+ self->size = packed_size;
+
+ /* Unpack the header */
+ header_read_length = PackFile_Header_unpack(interp, self->header, packed,
+ packed_size, self->options);
/* Set cursor to position after what we've read, allowing for padding to a
* 16 byte boundary. */
- header_read_length = PACKFILE_HEADER_BYTES + header->uuid_size;
header_read_length += PAD_16_B(header_read_length);
cursor = packed + (header_read_length / sizeof (opcode_t));
TRACE_PRINTF(("PackFile_unpack: pad=%d\n",
Something went wrong with that request. Please try again.