[runtime] Fix a crash on Windows during the cleanup phase caused by using a destroyed...
[mono-project.git] / mono / dis / declsec.c
blob3d6cd252366431fc9f6cb255f0aba34499c556c0
1 /*
2 * declsec.h: Support for the new declarative security attribute
3 * metadata format (2.0)
5 * Author:
6 * Sebastien Pouliot <sebastien@ximian.com>
8 * Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 */
11 #include <glib.h>
12 #include <math.h>
14 #include "mono/metadata/blob.h"
15 #include "mono/metadata/metadata.h"
16 #include "mono/metadata/mono-endian.h"
17 #include "mono/utils/mono-compiler.h"
19 #include "declsec.h"
20 #include "util.h"
22 static char*
23 declsec_20_get_classname (const char* p, const char **rptr)
25 int apos, cpos = 0;
26 char *c;
27 char *a;
28 char *result;
29 GString *res = g_string_new ("");
30 int len = mono_metadata_decode_value (p, &p);
32 c = (char *) p;
33 while ((*c++ != ',') && (cpos++ < len));
34 c++;
36 apos = cpos;
37 a = c;
38 while ((*a++ != ',') && (apos++ < len));
40 if (apos - cpos > 1) {
41 g_string_append_printf (res, "[%.*s]%.*s", apos - cpos, c, cpos, p);
42 } else {
43 /* in-assembly type aren't fully qualified (no comma) */
44 g_string_append_printf (res, "%.*s", cpos - 1, p);
47 p += len;
48 if (rptr)
49 *rptr = p;
51 result = res->str;
52 g_string_free (res, FALSE);
53 return result;
56 static gboolean
57 declsec_20_write_type (GString *str, char type)
59 switch (type) {
60 case MONO_TYPE_BOOLEAN:
61 g_string_append (str, "bool");
62 break;
63 case MONO_TYPE_SZARRAY:
64 g_string_append (str, "[]");
65 break;
66 case MONO_TYPE_SYSTEM_TYPE:
67 g_string_append (str, "type");
68 break;
69 case MONO_TYPE_STRING:
70 g_string_append (str, "string");
71 break;
72 default:
73 g_warning ("TODO type %d - please fill a bug report on this!", type);
74 return FALSE;
76 return TRUE;
79 static const char*
80 declsec_20_write_value (GString *str, char type, const char *value)
82 switch (type) {
83 case MONO_TYPE_U1:
84 g_string_append_printf (str, "%d", (unsigned char)*value);
85 return value + 1;
86 case MONO_TYPE_I1:
87 g_string_append_printf (str, "%d", *value);
88 return value + 1;
89 case MONO_TYPE_BOOLEAN:
90 g_string_append_printf (str, "%s", *value ? "true" : "false");
91 return value + 1;
92 case MONO_TYPE_CHAR:
93 g_string_append_printf (str, "0x%04X", read16 (value));
94 return value + 2;
95 case MONO_TYPE_U2:
96 g_string_append_printf (str, "%d", read16 (value));
97 return value + 2;
98 case MONO_TYPE_I2:
99 g_string_append_printf (str, "%d", (gint16)read16 (value));
100 return value + 2;
101 case MONO_TYPE_U4:
102 g_string_append_printf (str, "%d", read32 (value));
103 return value + 4;
104 case MONO_TYPE_I4:
105 g_string_append_printf (str, "%d", (gint32)read32 (value));
106 return value + 4;
107 case MONO_TYPE_U8:
108 g_string_append_printf (str, "%lld", (long long)read64 (value));
109 return value + 8;
110 case MONO_TYPE_I8:
111 g_string_append_printf (str, "%lld", (long long)read64 (value));
112 return value + 8;
113 case MONO_TYPE_R4: {
114 float val;
115 int inf;
116 readr4 (value, &val);
117 inf = dis_isinf (val);
118 if (inf == -1)
119 g_string_append_printf (str, "0xFF800000"); /* negative infinity */
120 else if (inf == 1)
121 g_string_append_printf (str, "0x7F800000"); /* positive infinity */
122 else if (dis_isnan (val))
123 g_string_append_printf (str, "0xFFC00000"); /* NaN */
124 else
125 g_string_append_printf (str, "%.8g", val);
126 return value + 4;
128 case MONO_TYPE_R8: {
129 double val;
130 int inf;
131 readr8 (value, &val);
132 inf = dis_isinf (val);
133 if (inf == -1)
134 g_string_append_printf (str, "0xFFF00000000000000"); /* negative infinity */
135 else if (inf == 1)
136 g_string_append_printf (str, "0x7FFF0000000000000"); /* positive infinity */
137 else if (isnan (val))
138 g_string_append_printf (str, "0xFFF80000000000000"); /* NaN */
139 else
140 g_string_append_printf (str, "%.17g", val);
141 return value + 8;
143 case MONO_TYPE_STRING:
144 if (*value == (char)0xff) {
145 g_string_append (str, "nullref");
146 return value + 1;
147 } else {
148 int len = mono_metadata_decode_value (value, &value);
149 g_string_append_printf (str, "'%.*s'", len, value);
150 return value + len;
152 case MONO_TYPE_SYSTEM_TYPE: {
153 char *cname = declsec_20_get_classname (value, NULL);
154 int len = mono_metadata_decode_value (value, &value);
155 g_string_append (str, cname);
156 g_free (cname);
157 return value + len;
160 return 0;
163 char*
164 dump_declsec_entry20 (MonoImage *m, const char* p, const char *indent)
166 int i, num;
167 char *result;
168 GString *res = g_string_new ("");
170 if (*p++ != MONO_DECLSEC_FORMAT_20)
171 return NULL;
173 g_string_append (res, "{");
175 /* number of encoded permission attributes */
176 num = mono_metadata_decode_value (p, &p);
178 for (i = 0; i < num; i++) {
179 int len, j, pos = 0, param_len;
180 char *param_start;
181 char *s = declsec_20_get_classname (p, &p);
182 g_string_append_printf (res, "%s = {", s);
183 g_free (s);
185 /* optional parameters length */
186 param_len = mono_metadata_decode_value (p, &p);
187 param_start = (char *) p;
189 /* number of parameters */
190 pos = mono_metadata_decode_value (p, &p);
191 for (j = 0; j < pos; j++) {
192 int k, elem;
193 int type = *p++;
195 switch (type) {
196 case MONO_DECLSEC_FIELD:
197 /* not sure if/how we can get this in a declarative security attribute... */
198 g_string_append (res, "field ");
199 break;
200 case MONO_DECLSEC_PROPERTY:
201 g_string_append (res, "property ");
202 break;
203 default:
204 g_warning ("TODO %d - please fill a bug report on this!", type);
205 break;
208 type = *p++;
210 if (type == MONO_DECLSEC_ENUM) {
211 s = declsec_20_get_classname (p, &p);
212 len = mono_metadata_decode_value (p, &p);
213 g_string_append_printf (res, "enum %s '%.*s' = ", s, len, p);
214 g_free (s);
215 p += len;
216 /* TODO: we must detect the size of the enum element (from the type ? length ?)
217 * note: ildasm v2 has some problem decoding them too and doesn't
218 * seems to rely on the type (as the other assembly isn't loaded) */
219 g_string_append_printf (res, "int32(%d)", read32 (p));
220 p += 4;
221 } else {
222 int arraytype = 0;
223 if (type == MONO_TYPE_SZARRAY) {
224 arraytype = *p++;
225 declsec_20_write_type (res, arraytype);
227 declsec_20_write_type (res, type);
229 len = mono_metadata_decode_value (p, &p);
230 g_string_append_printf (res, " '%.*s' = ", len, p);
231 p += len;
233 if (type == MONO_TYPE_SZARRAY) {
234 type = arraytype;
235 declsec_20_write_type (res, type);
236 elem = read32 (p);
237 p += 4;
238 g_string_append_printf (res, "[%d]", elem);
239 } else {
240 declsec_20_write_type (res, type);
241 elem = 1;
243 g_string_append (res, "(");
245 /* write value - or each element in the array */
246 for (k = 0; k < elem; k++) {
247 p = declsec_20_write_value (res, type, p);
248 /* separate array elements */
249 if (k < elem - 1)
250 g_string_append (res, " ");
253 if (j < pos - 1)
254 g_string_append_printf (res, ")\n%s", indent);
255 else
256 g_string_append (res, ")");
261 if (i < num - 1)
262 g_string_append_printf (res, "},\n%s", indent);
263 else
264 g_string_append (res, "}");
266 if (param_len > 0)
267 p = param_start + param_len;
269 g_string_append (res, "}");
271 result = res->str;
272 g_string_free (res, FALSE);
273 return result;