diff --git a/portable_endian.h b/portable_endian.h new file mode 100644 index 0000000..da0d140 --- /dev/null +++ b/portable_endian.h @@ -0,0 +1,122 @@ +// "License": Public Domain +// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to +// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it +// an example on how to get the endian conversion functions on different platforms. + +/* Originally cloned from https://gist.github.com/PkmX/63dd23f28ba885be53a5 + * Commit was: 1eca2ab34f2301b9641aa73d1016b951fff3fc39 + * Re-published at https://github.com/BenWiederhake/portable-endian.h to provide a means to submit patches and report issues. */ + +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif diff --git a/tl-parser.c b/tl-parser.c index a010d42..524b196 100644 --- a/tl-parser.c +++ b/tl-parser.c @@ -35,6 +35,7 @@ #include #include #include +#include "portable_endian.h" #include "tl-parser-tree.h" #include "tl-parser.h" #include "tl-tl.h" @@ -62,6 +63,9 @@ int total_functions_num; #define talloc0(a) calloc(a,1) #define tstrdup(a) strdup(a) +typedef char error_int_must_be_4_byte[(sizeof (int) == 4) ? 1 : -1]; +typedef char error_long_long_must_be_8_byte[(sizeof (long long) == 8) ? 1 : -1]; + char curch; struct parse parse; @@ -2723,6 +2727,7 @@ int num = 0; void wint (int a) { // printf ("%d ", a); + a = htole32 (a); assert (write (__f, &a, 4) == 4); } @@ -2733,23 +2738,20 @@ void wdata (const void *x, int len) { void wstr (const char *s) { if (s) { // printf ("\"%s\" ", s); - if (schema_version < 1) { - wint (strlen (s)); - wdata (s, strlen (s)); + int x = strlen (s); + if (x <= 254) { + unsigned char x_c = (unsigned char)x; + assert (write (__f, &x_c, 1) == 1); } else { - int x = strlen (s); - if (x <= 254) { - assert (write (__f, &x, 1) == 1); - } else { - fprintf (stderr, "String is too big...\n"); - assert (0); - } - wdata (s, x); - x ++; - int t = 0; - if (x & 3) { - wdata (&t, 4 - (x & 3)); - } + fprintf (stderr, "String is too big...\n"); + assert (0); + } + wdata (s, x); + x ++; // The header, containing the length, which is 1 byte + int t = 0; + if (x & 3) { + // Let's hope it's truly zero on every platform + wdata (&t, 4 - (x & 3)); } } else { // printf (" "); @@ -2759,6 +2761,7 @@ void wstr (const char *s) { void wll (long long a) { // printf ("%lld ", a); + a = htole64 (a); assert (write (__f, &a, 8) == 8); } @@ -2827,25 +2830,7 @@ void write_args (struct tl_combinator_tree *T, struct tree_var_value **v, int *l write_args (T->right, v, last_var); return; } - if (schema_version == 1) { - wint (TLS_ARG); - } if (schema_version == 2) { - wint (TLS_ARG_V2); - } else { - wint (-3); - } - if (T->act == act_question_mark) { - if (schema_version >= 1) { - assert (0); - } else { - wint (-100); - } - return; - } - if (schema_version >= 1) { - } else { - wint (-99); - } + wint (TLS_ARG_V2); assert (T->act == act_field); assert (T->left); wstr (T->data && strcmp (T->data, "_") ? T->data : 0); @@ -2860,21 +2845,12 @@ void write_args (struct tl_combinator_tree *T, struct tree_var_value **v, int *l tl_set_var_value_num (v, T, 0, (*last_var) - 1); } else { write_field_flags (f); - if (schema_version <= 1) { - wint (-1); - } } write_tree (T->left, 0, v, last_var); } void write_array (struct tl_combinator_tree *T, struct tree_var_value **v, int *last_var) { - if (schema_version == 1) { - wint (TLS_TREE_ARRAY); - } else if (schema_version == 2) { - wint (TLS_ARRAY); - } else { - wint (-8); - } + wint (TLS_ARRAY); write_tree (T->left, 0, v, last_var); write_tree (T->right, 0, v, last_var); } @@ -2882,36 +2858,22 @@ void write_array (struct tl_combinator_tree *T, struct tree_var_value **v, int * void write_type_rec (struct tl_combinator_tree *T, int cc, struct tree_var_value **v, int *last_var) { if (T->act == act_arg) { write_type_rec (T->left, cc + 1, v, last_var); - if (schema_version >= 2) { - if (T->right->type == type_num_value || T->right->type == type_num) { - wint (TLS_EXPR_NAT); - } else { - wint (TLS_EXPR_TYPE); - } + if (T->right->type == type_num_value || T->right->type == type_num) { + wint (TLS_EXPR_NAT); + } else { + wint (TLS_EXPR_TYPE); } write_tree (T->right, 0, v, last_var); } else { assert (T->act == act_var || T->act == act_type); if (T->act == act_var) { assert (!cc); - if (schema_version == 1) { - wint (TLS_TREE_TYPE_VAR); - } else if (schema_version == 2) { - wint (TLS_TYPE_VAR); - } else { - wint (-6); - } + wint (TLS_TYPE_VAR); wint (tl_get_var_value_num (v, T->data)); write_var_type_flags (T->flags); //wint (T->flags); } else { - if (schema_version == 1) { - wint (TLS_TREE_TYPE); - } else if (schema_version == 2) { - wint (TLS_TYPE_EXPR); - } else { - wint (-7); - } + wint (TLS_TYPE_EXPR); struct tl_type *t = T->data; wint (t->name); write_type_flags (T->flags); @@ -2923,10 +2885,6 @@ void write_type_rec (struct tl_combinator_tree *T, int cc, struct tree_var_value } void write_opt_type (struct tl_combinator_tree *T, struct tree_var_value **v, int *last_var) { - if (schema_version >= 1) { - } else { - wint (-20); - } wint (tl_get_var_value_num (v, T->left->data)); wint (T->left->type_flags); // write_tree (T->right, 0, v, last_var); @@ -2952,31 +2910,19 @@ void write_tree (struct tl_combinator_tree *T, int extra, struct tree_var_value switch (T->type) { case type_list_item: case type_list: - if (schema_version >= 1) { - if (extra) { - wint (schema_version >= 2 ? TLS_COMBINATOR_RIGHT_V2 : TLS_COMBINATOR_RIGHT); - } - } else { - wint (extra ? -1 : -2); + if (extra) { + wint (TLS_COMBINATOR_RIGHT_V2); } wint (count_list_size (T)); write_args (T, v, last_var); break; case type_num_value: - wint (schema_version >= 1 ? schema_version >= 2 ? (int)TLS_NAT_CONST : (int)TLS_TREE_NAT_CONST : -4); - if (schema_version >= 2) { - wint (T->type_flags); - } else { - wll (T->type_flags); - } + wint ((int)TLS_NAT_CONST); + wint (T->type_flags); break; case type_num: - wint (schema_version >= 1 ? schema_version >= 2 ? (int)TLS_NAT_VAR : (int)TLS_TREE_NAT_VAR : -5); - if (schema_version >= 2) { - wint (T->type_flags); - } else { - wll (T->type_flags); - } + wint ((int)TLS_NAT_VAR); + wint (T->type_flags); wint (tl_get_var_value_num (v, T->data)); break; case type_type: @@ -2995,7 +2941,7 @@ void write_tree (struct tl_combinator_tree *T, int extra, struct tree_var_value } void write_type (struct tl_type *t) { - wint (schema_version >= 1 ? TLS_TYPE : 1); + wint (TLS_TYPE); wint (t->name); wstr (t->id); wint (t->constructors_num); @@ -3016,36 +2962,29 @@ void write_combinator (struct tl_constructor *c) { int x = 0; assert (c->right); if (c->left) { - if (schema_version >= 1 && is_builtin_type (c->id)) { + if (is_builtin_type (c->id)) { wint (TLS_COMBINATOR_LEFT_BUILTIN); } else { - if (schema_version >= 1) { - wint (TLS_COMBINATOR_LEFT); - } + wint (TLS_COMBINATOR_LEFT); + // FIXME: What is that? // wint (count_list_size (c->left)); write_tree (c->left, 0, &T, &x); } } else { - if (schema_version >= 1) { - wint (TLS_COMBINATOR_LEFT); - wint (0); - } else { - wint (-11); - } - } - if (schema_version >= 1) { - wint (schema_version >= 2 ? TLS_COMBINATOR_RIGHT_V2 : TLS_COMBINATOR_RIGHT); + wint (TLS_COMBINATOR_LEFT); + wint (0); } + wint (TLS_COMBINATOR_RIGHT_V2); write_tree (c->right, 1, &T, &x); } void write_constructor (struct tl_constructor *c) { - wint (schema_version >= 1 ? TLS_COMBINATOR : 2); + wint (TLS_COMBINATOR); write_combinator (c); } void write_function (struct tl_constructor *c) { - wint (schema_version >= 1 ? TLS_COMBINATOR : 3); + wint (TLS_COMBINATOR); write_combinator (c); } @@ -3056,31 +2995,21 @@ void write_type_constructors (struct tl_type *t) { } } -int MAGIC = 0x850230aa; void write_types (int f) { __f = f; - if (schema_version == 1) { - wint (TLS_SCHEMA); - } else if (schema_version == 2) { - wint (TLS_SCHEMA_V2); - } else { - wint (MAGIC); - } - if (schema_version >= 1) { - wint (0); - wint (time (0)); - } + wint (TLS_SCHEMA_V2); + wint (0); +#ifdef TL_PARSER_NEED_TIME + wint (time (0)); +#else + /* Make the tlo reproducible by default. Rationale: https://wiki.debian.org/ReproducibleBuilds/Howto#Introduction */ + wint (0); +#endif num = 0; - if (schema_version >= 1) { - wint (total_types_num); - } + wint (total_types_num); tree_act_tl_type (tl_type_tree, write_type); - if (schema_version >= 1) { - wint (total_constructors_num); - } + wint (total_constructors_num); tree_act_tl_type (tl_type_tree, write_type_constructors); - if (schema_version >= 1) { - wint (total_functions_num); - } + wint (total_functions_num); tree_act_tl_constructor (tl_function_tree, write_function); } diff --git a/tl-tl.h b/tl-tl.h index 4ee6e2e..8bc0a70 100644 --- a/tl-tl.h +++ b/tl-tl.h @@ -25,22 +25,17 @@ #ifndef __TL_TL_H__ #define __TL_TL_H__ -#define TLS_SCHEMA 0xf19d9e38 +// Current tl-tl schema is V2 +// See https://core.telegram.org/mtproto/TL-tl + +#define TLS_SCHEMA_V2 0x3a2f9be2 #define TLS_TYPE 0x12eb4386 #define TLS_COMBINATOR 0x5c0a1ed5 #define TLS_COMBINATOR_LEFT_BUILTIN 0xcd211f63 #define TLS_COMBINATOR_LEFT 0x4c12c6d9 -#define TLS_COMBINATOR_RIGHT 0xd325b367 -#define TLS_ARG 0x46afe232 -#define TLS_TREE_NAT_CONST 0xc09f07d7 -#define TLS_TREE_NAT_VAR 0x90ea6f58 -#define TLS_TREE_TYPE_VAR 0x1caa237a -#define TLS_TREE_ARRAY 0x80479360 -#define TLS_TREE_TYPE 0x10f32190 - -#define TLS_SCHEMA_V2 0x3a2f9be2 #define TLS_COMBINATOR_RIGHT_V2 0x2c064372 #define TLS_ARG_V2 0x29dfe61b + #define TLS_EXPR_TYPE 0xecc9da78 #define TLS_EXPR_NAT 0xdcb49bd8 @@ -49,4 +44,12 @@ #define TLS_TYPE_VAR 0x0142ceae #define TLS_ARRAY 0xd9fb20de #define TLS_TYPE_EXPR 0xc1863d08 + +/* Deprecated (old versions), read-only */ +#define TLS_TREE_NAT_CONST 0xc09f07d7 +#define TLS_TREE_NAT_VAR 0x90ea6f58 +#define TLS_TREE_TYPE_VAR 0x1caa237a +#define TLS_TREE_ARRAY 0x80479360 +#define TLS_TREE_TYPE 0x10f32190 + #endif diff --git a/tlc.c b/tlc.c index 3d63e2a..cd0300f 100644 --- a/tlc.c +++ b/tlc.c @@ -45,14 +45,12 @@ int verbosity; int output_expressions; -int schema_version = 2; void usage (void) { printf ("usage: tl-parser [-v] [-h] \n" "\tTL compiler\n" "\t-v\toutput statistical and debug information into stderr\n" "\t-E\twhenever is possible output to stdout expressions\n" "\t-e \texport serialized schema to file\n" - "\t-w\t custom version of serialized schema (0 - very old, 1 - old, 2 - current (default))\n" ); exit (2); } @@ -125,9 +123,6 @@ int main (int argc, char **argv) { case 'e': vkext_file = optarg; break; - case 'w': - schema_version = atoi (optarg); - break; case 'v': verbosity++; break;