1use crate::buffer::{Reader, Writer};
19use crate::config::Config;
20use crate::error::Error;
21use crate::meta::TypeMeta;
22use crate::resolver::type_resolver::NO_USER_TYPE_ID;
23use crate::resolver::{TypeInfo, TypeResolver};
24use std::collections::HashMap;
25use std::rc::Rc;
26
27#[derive(Default)]
32pub struct MetaWriterResolver {
33 type_id_index_map: HashMap<std::any::TypeId, usize>,
34 type_index_index_map: Vec<usize>,
35 next_index: usize,
36}
37
38const MIN_REMOTE_TYPE_META_LIMIT: usize = 8192;
39const NO_WRITTEN_TYPE_INDEX: usize = usize::MAX;
40
41#[allow(dead_code)]
42impl MetaWriterResolver {
43 #[inline(always)]
46 pub fn write_type_meta(
47 &mut self,
48 writer: &mut Writer,
49 type_id: std::any::TypeId,
50 type_resolver: &TypeResolver,
51 ) -> Result<(), Error> {
52 match self.type_id_index_map.get(&type_id) {
53 Some(&index) => {
54 writer.write_var_u32(((index as u32) << 1) | 1);
56 }
57 None => {
58 let index = self.next_index;
60 self.next_index += 1;
61 writer.write_var_u32((index as u32) << 1);
62 self.type_id_index_map.insert(type_id, index);
63 let type_def = type_resolver.get_type_info(&type_id)?.get_type_def();
65 writer.write_bytes(&type_def);
66 }
67 }
68 Ok(())
69 }
70
71 #[inline(always)]
73 pub fn write_type_meta_fast(
74 &mut self,
75 writer: &mut Writer,
76 type_id: std::any::TypeId,
77 type_index: u32,
78 type_resolver: &TypeResolver,
79 ) -> Result<(), Error> {
80 let type_index = type_index as usize;
81 if let Some(&index) = self.type_index_index_map.get(type_index) {
82 if index != NO_WRITTEN_TYPE_INDEX {
83 writer.write_var_u32(((index as u32) << 1) | 1);
84 return Ok(());
85 }
86 }
87
88 let index = self.next_index;
89 self.next_index += 1;
90 writer.write_var_u32((index as u32) << 1);
91 if type_index >= self.type_index_index_map.len() {
92 self.type_index_index_map
93 .resize(type_index + 1, NO_WRITTEN_TYPE_INDEX);
94 }
95 self.type_index_index_map[type_index] = index;
96 let type_meta = type_resolver.get_type_meta_by_index_ref(&type_id, type_index as u32)?;
97 writer.write_bytes(type_meta.get_bytes());
98 Ok(())
99 }
100
101 #[inline(always)]
102 pub fn reset(&mut self) {
103 self.type_id_index_map.clear();
104 self.type_index_index_map.clear();
105 self.next_index = 0;
106 }
107}
108
109#[derive(Default)]
114pub struct MetaReaderResolver {
115 pub reading_type_infos: Vec<Rc<TypeInfo>>,
116 parsed_type_infos: HashMap<i64, Rc<TypeInfo>>,
117 remote_schema_versions_by_type: HashMap<String, usize>,
118 total_accepted_schema_versions: usize,
119 cached_meta_header: i64,
120 cached_type_info: Option<Rc<TypeInfo>>,
121}
122
123impl MetaReaderResolver {
124 #[inline(always)]
125 pub fn get(&self, index: usize) -> Option<&Rc<TypeInfo>> {
126 self.reading_type_infos.get(index)
127 }
128
129 #[inline(always)]
132 pub fn read_type_meta(
133 &mut self,
134 reader: &mut Reader,
135 type_resolver: &TypeResolver,
136 config: &Config,
137 ) -> Result<Rc<TypeInfo>, Error> {
138 let index_marker = reader.read_var_u32()?;
139 let is_ref = (index_marker & 1) == 1;
140 let index = (index_marker >> 1) as usize;
141
142 if is_ref {
143 self.reading_type_infos.get(index).cloned().ok_or_else(|| {
145 Error::type_error(format!("TypeInfo not found for type index: {}", index))
146 })
147 } else {
148 let meta_header = reader.read_i64()?;
150 if let Some(type_info) = self
151 .cached_type_info
152 .as_ref()
153 .filter(|_| self.cached_meta_header == meta_header)
154 {
155 self.reading_type_infos.push(type_info.clone());
160 TypeMeta::skip_bytes_for_validated_header(reader, meta_header)?;
161 return Ok(type_info.clone());
162 }
163 if let Some(type_info) = self.parsed_type_infos.get(&meta_header) {
164 self.cached_meta_header = meta_header;
169 self.cached_type_info = Some(type_info.clone());
170 self.reading_type_infos.push(type_info.clone());
171 TypeMeta::skip_bytes_for_validated_header(reader, meta_header)?;
172 Ok(type_info.clone())
173 } else {
174 let type_def_start = reader.get_cursor() - std::mem::size_of::<i64>();
175 self.read_remote_type_meta(
176 reader,
177 type_resolver,
178 config,
179 meta_header,
180 type_def_start,
181 )
182 }
183 }
184 }
185
186 #[cold]
187 #[inline(never)]
188 fn read_remote_type_meta(
189 &mut self,
190 reader: &mut Reader,
191 type_resolver: &TypeResolver,
192 config: &Config,
193 meta_header: i64,
194 type_def_start: usize,
195 ) -> Result<Rc<TypeInfo>, Error> {
196 let type_meta = Rc::new(TypeMeta::from_bytes_with_header(
197 reader,
198 type_resolver,
199 meta_header,
200 config.max_type_fields(),
201 config.max_type_meta_bytes(),
202 )?);
203 let remote_type_def = reader.sub_slice(type_def_start, reader.get_cursor())?;
204
205 let namespace = type_meta.get_namespace();
206 let type_name = type_meta.get_type_name();
207 let register_by_name = !namespace.original.is_empty() || !type_name.original.is_empty();
208 let mut remote_schema_key = None;
209 let type_info = if register_by_name {
210 if let Some(local_type_info) =
211 type_resolver.get_type_info_by_name(&namespace.original, &type_name.original)
212 {
213 if local_type_info.get_type_meta_ref().get_bytes() == remote_type_def {
214 local_type_info
215 } else {
216 remote_schema_key =
217 Some(self.check_remote_type_meta_limit(&type_meta, config)?);
218 Rc::new(TypeInfo::from_remote_meta(
219 type_meta.clone(),
220 Some(local_type_info.get_harness()),
221 Some(local_type_info.get_type_id() as u32),
222 Some(local_type_info.get_user_type_id()),
223 ))
224 }
225 } else {
226 remote_schema_key = Some(self.check_remote_type_meta_limit(&type_meta, config)?);
227 Rc::new(TypeInfo::from_remote_meta(
228 type_meta.clone(),
229 None,
230 None,
231 None,
232 ))
233 }
234 } else {
235 let type_id = type_meta.get_type_id();
236 let user_type_id = type_meta.get_user_type_id();
237 let local_type_info = if user_type_id != NO_USER_TYPE_ID {
238 type_resolver.get_user_type_info_by_id(user_type_id)
239 } else {
240 type_resolver.get_type_info_by_id(type_id)
241 };
242 if let Some(local_type_info) = local_type_info {
243 if local_type_info.get_type_meta_ref().get_bytes() == remote_type_def {
244 local_type_info
245 } else {
246 remote_schema_key =
247 Some(self.check_remote_type_meta_limit(&type_meta, config)?);
248 Rc::new(TypeInfo::from_remote_meta(
249 type_meta.clone(),
250 Some(local_type_info.get_harness()),
251 Some(local_type_info.get_type_id() as u32),
252 Some(local_type_info.get_user_type_id()),
253 ))
254 }
255 } else {
256 remote_schema_key = Some(self.check_remote_type_meta_limit(&type_meta, config)?);
257 Rc::new(TypeInfo::from_remote_meta(
258 type_meta.clone(),
259 None,
260 None,
261 None,
262 ))
263 }
264 };
265
266 self.parsed_type_infos
267 .insert(meta_header, type_info.clone());
268 self.cached_meta_header = meta_header;
269 self.cached_type_info = Some(type_info.clone());
270 self.reading_type_infos.push(type_info.clone());
271 if let Some(remote_schema_key) = remote_schema_key {
272 self.record_remote_type_meta(remote_schema_key);
273 }
274 Ok(type_info)
275 }
276
277 #[cold]
278 #[inline(never)]
279 fn check_remote_type_meta_limit(
280 &self,
281 type_meta: &TypeMeta,
282 config: &Config,
283 ) -> Result<String, Error> {
284 let namespace = type_meta.get_namespace();
285 let type_name = type_meta.get_type_name();
286 let key = if !namespace.original.is_empty() || !type_name.original.is_empty() {
287 format!("n{}\0{}", namespace.original, type_name.original)
288 } else {
289 format!("i{}", type_meta.get_user_type_id())
290 };
291
292 let versions_for_type = self
293 .remote_schema_versions_by_type
294 .get(&key)
295 .copied()
296 .unwrap_or(0);
297 if versions_for_type >= config.max_schema_versions_per_type() {
298 return Err(Error::invalid_data(format!(
299 "remote schema version limit exceeded for one type. The data may be malicious. If the data is not malicious, please increase max_schema_versions_per_type={}",
300 config.max_schema_versions_per_type()
301 )));
302 }
303
304 let accepted_type_count =
305 self.remote_schema_versions_by_type.len() + if versions_for_type == 0 { 1 } else { 0 };
306 let global_limit = usize::max(
307 MIN_REMOTE_TYPE_META_LIMIT,
308 accepted_type_count * config.max_average_schema_versions_per_type(),
309 );
310 if self.total_accepted_schema_versions >= global_limit {
311 return Err(Error::invalid_data(format!(
312 "remote schema version limit exceeded globally. The data may be malicious. If the data is not malicious, please increase max_average_schema_versions_per_type={}",
313 config.max_average_schema_versions_per_type()
314 )));
315 }
316
317 Ok(key)
318 }
319
320 fn record_remote_type_meta(&mut self, key: String) {
321 let versions_for_type = self
322 .remote_schema_versions_by_type
323 .get(&key)
324 .copied()
325 .unwrap_or(0);
326 self.remote_schema_versions_by_type
327 .insert(key, versions_for_type + 1);
328 self.total_accepted_schema_versions += 1;
329 }
330
331 #[inline(always)]
332 pub fn reset(&mut self) {
333 self.reading_type_infos.clear();
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340 use crate::config::Config;
341 use crate::context::{ReadContext, WriteContext};
342 use crate::meta::{
343 FieldInfo, FieldType, MetaString, NAMESPACE_ENCODER, NAMESPACE_ENCODINGS,
344 TYPE_NAME_ENCODER, TYPE_NAME_ENCODINGS,
345 };
346 use crate::serializer::{ForyDefault, Serializer};
347 use crate::TypeId;
348
349 struct LocalExt;
350
351 impl ForyDefault for LocalExt {
352 fn fory_default() -> Self {
353 LocalExt
354 }
355 }
356
357 impl Serializer for LocalExt {
358 fn fory_write_data(&self, _context: &mut WriteContext) -> Result<(), Error> {
359 Ok(())
360 }
361
362 fn fory_read_data(_context: &mut ReadContext) -> Result<Self, Error> {
363 Ok(LocalExt)
364 }
365
366 fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
367 Self::fory_get_type_id(type_resolver)
368 }
369
370 fn as_any(&self) -> &dyn std::any::Any {
371 self
372 }
373 }
374
375 fn read_type_def(
376 resolver: &mut MetaReaderResolver,
377 config: &Config,
378 type_def: &[u8],
379 ) -> Result<Rc<TypeInfo>, Error> {
380 let type_resolver = TypeResolver::default();
381 read_type_def_with_type_resolver(resolver, config, &type_resolver, type_def)
382 }
383
384 fn read_type_def_with_type_resolver(
385 resolver: &mut MetaReaderResolver,
386 config: &Config,
387 type_resolver: &TypeResolver,
388 type_def: &[u8],
389 ) -> Result<Rc<TypeInfo>, Error> {
390 let mut bytes = vec![];
391 let mut writer = Writer::from_buffer(&mut bytes);
392 writer.write_var_u32(0);
393 writer.write_bytes(type_def);
394 let mut reader = Reader::new(&bytes);
395 resolver.read_type_meta(&mut reader, type_resolver, config)
396 }
397
398 #[test]
399 fn type_meta_field_limit_rejects_large_struct() {
400 let meta = TypeMeta::new(
401 TypeId::STRUCT as u32,
402 9001,
403 MetaString::get_empty().clone(),
404 MetaString::get_empty().clone(),
405 false,
406 vec![
407 FieldInfo::new("a", FieldType::new(crate::type_id::INT32, false, vec![])),
408 FieldInfo::new("b", FieldType::new(crate::type_id::INT32, false, vec![])),
409 ],
410 )
411 .unwrap();
412 let config = Config {
413 max_type_fields: 1,
414 ..Default::default()
415 };
416 let err = read_type_def(
417 &mut MetaReaderResolver::default(),
418 &config,
419 meta.get_bytes(),
420 )
421 .unwrap_err()
422 .to_string();
423 assert!(err.contains("max_type_fields"));
424 }
425
426 #[test]
427 fn type_meta_body_limit_rejects_large_metadata() {
428 let meta = TypeMeta::new(
429 TypeId::STRUCT as u32,
430 9001,
431 MetaString::get_empty().clone(),
432 MetaString::get_empty().clone(),
433 false,
434 vec![FieldInfo::new(
435 "a",
436 FieldType::new(crate::type_id::INT32, false, vec![]),
437 )],
438 )
439 .unwrap();
440 let config = Config {
441 max_type_meta_bytes: 1,
442 ..Default::default()
443 };
444 let err = read_type_def(
445 &mut MetaReaderResolver::default(),
446 &config,
447 meta.get_bytes(),
448 )
449 .unwrap_err()
450 .to_string();
451 assert!(err.contains("max_type_meta_bytes"));
452 }
453
454 #[test]
455 fn schema_limit_tracks_unknown_struct_types_separately() {
456 fn type_def(user_type_id: u32, field_name: &str) -> Vec<u8> {
457 TypeMeta::new(
458 TypeId::STRUCT as u32,
459 user_type_id,
460 MetaString::get_empty().clone(),
461 MetaString::get_empty().clone(),
462 false,
463 vec![FieldInfo::new(
464 field_name,
465 FieldType::new(crate::type_id::INT32, false, vec![]),
466 )],
467 )
468 .unwrap()
469 .get_bytes()
470 .to_vec()
471 }
472
473 let config = Config {
474 max_schema_versions_per_type: 1,
475 ..Default::default()
476 };
477
478 let mut resolver = MetaReaderResolver::default();
479 read_type_def(&mut resolver, &config, &type_def(9001, "a")).unwrap();
480 read_type_def(&mut resolver, &config, &type_def(9002, "a")).unwrap();
481
482 let err = read_type_def(&mut resolver, &config, &type_def(9001, "b"))
483 .unwrap_err()
484 .to_string();
485 assert!(err.contains("max_schema_versions_per_type"));
486 }
487
488 #[test]
489 fn schema_limit_rejects_extra_versions_for_type() {
490 let meta = TypeMeta::new(
491 TypeId::STRUCT as u32,
492 9001,
493 MetaString::get_empty().clone(),
494 MetaString::get_empty().clone(),
495 false,
496 vec![FieldInfo::new(
497 "a",
498 FieldType::new(crate::type_id::INT32, false, vec![]),
499 )],
500 )
501 .unwrap();
502 let type_def = meta.get_bytes().to_vec();
503
504 let config = Config {
505 max_schema_versions_per_type: 1,
506 ..Default::default()
507 };
508 let mut resolver = MetaReaderResolver::default();
509 let mut bytes = vec![];
510 let mut writer = Writer::from_buffer(&mut bytes);
511 writer.write_var_u32(0);
512 writer.write_bytes(&type_def);
513 let mut reader = Reader::new(&bytes);
514 resolver
515 .read_type_meta(&mut reader, &TypeResolver::default(), &config)
516 .unwrap();
517
518 let changed = TypeMeta::new(
519 TypeId::STRUCT as u32,
520 9001,
521 MetaString::get_empty().clone(),
522 MetaString::get_empty().clone(),
523 false,
524 vec![FieldInfo::new(
525 "b",
526 FieldType::new(crate::type_id::INT32, false, vec![]),
527 )],
528 )
529 .unwrap();
530 let mut bytes = vec![];
531 let mut writer = Writer::from_buffer(&mut bytes);
532 writer.write_var_u32(0);
533 writer.write_bytes(changed.get_bytes());
534 let mut reader = Reader::new(&bytes);
535 let err = resolver
536 .read_type_meta(&mut reader, &TypeResolver::default(), &config)
537 .unwrap_err()
538 .to_string();
539 assert!(err.contains("max_schema_versions_per_type"));
540 }
541
542 #[test]
543 fn schema_limit_check_is_not_recorded() {
544 let config = Config {
545 max_schema_versions_per_type: 1,
546 ..Default::default()
547 };
548 let mut resolver = MetaReaderResolver::default();
549 let checked = TypeMeta::new(
550 TypeId::STRUCT as u32,
551 9001,
552 MetaString::get_empty().clone(),
553 MetaString::get_empty().clone(),
554 false,
555 vec![FieldInfo::new(
556 "a",
557 FieldType::new(crate::type_id::INT32, false, vec![]),
558 )],
559 )
560 .unwrap();
561 let accepted = TypeMeta::new(
562 TypeId::STRUCT as u32,
563 9001,
564 MetaString::get_empty().clone(),
565 MetaString::get_empty().clone(),
566 false,
567 vec![FieldInfo::new(
568 "b",
569 FieldType::new(crate::type_id::INT32, false, vec![]),
570 )],
571 )
572 .unwrap();
573
574 resolver
575 .check_remote_type_meta_limit(&checked, &config)
576 .unwrap();
577
578 let mut bytes = vec![];
579 let mut writer = Writer::from_buffer(&mut bytes);
580 writer.write_var_u32(0);
581 writer.write_bytes(accepted.get_bytes());
582 let mut reader = Reader::new(&bytes);
583 resolver
584 .read_type_meta(&mut reader, &TypeResolver::default(), &config)
585 .unwrap();
586 }
587
588 #[test]
589 fn non_struct_type_meta_uses_limit() {
590 let config = Config {
591 max_schema_versions_per_type: 1,
592 ..Default::default()
593 };
594 let mut resolver = MetaReaderResolver::default();
595 let namespace = NAMESPACE_ENCODER
596 .encode_with_encodings("example", NAMESPACE_ENCODINGS)
597 .unwrap();
598 let type_name = TYPE_NAME_ENCODER
599 .encode_with_encodings("RemoteEnum", TYPE_NAME_ENCODINGS)
600 .unwrap();
601 let first = TypeMeta::new(
602 TypeId::NAMED_ENUM as u32,
603 NO_USER_TYPE_ID,
604 namespace.clone(),
605 type_name.clone(),
606 true,
607 vec![],
608 )
609 .unwrap();
610 let second = TypeMeta::new(
611 TypeId::NAMED_EXT as u32,
612 NO_USER_TYPE_ID,
613 namespace,
614 type_name,
615 true,
616 vec![],
617 )
618 .unwrap();
619
620 let key = resolver
621 .check_remote_type_meta_limit(&first, &config)
622 .unwrap();
623 resolver.record_remote_type_meta(key);
624
625 let err = resolver
626 .check_remote_type_meta_limit(&second, &config)
627 .unwrap_err()
628 .to_string();
629 assert!(err.contains("max_schema_versions_per_type"));
630 }
631
632 #[test]
633 fn exact_local_non_struct_type_meta_bypasses_limit() {
634 let config = Config {
635 max_schema_versions_per_type: 1,
636 ..Default::default()
637 };
638 let mut type_resolver = TypeResolver::default();
639 type_resolver
640 .register_serializer_by_name::<LocalExt>("example.SharedExt")
641 .unwrap();
642 let type_resolver = type_resolver.build_final_type_resolver().unwrap();
643 let local_info = type_resolver
644 .get_type_info_by_name("example", "SharedExt")
645 .unwrap();
646 let exact = local_info.get_type_meta_ref().get_bytes().to_vec();
647
648 let mut resolver = MetaReaderResolver::default();
649 read_type_def_with_type_resolver(&mut resolver, &config, &type_resolver, &exact).unwrap();
650
651 let namespace = NAMESPACE_ENCODER
652 .encode_with_encodings("example", NAMESPACE_ENCODINGS)
653 .unwrap();
654 let type_name = TYPE_NAME_ENCODER
655 .encode_with_encodings("SharedExt", TYPE_NAME_ENCODINGS)
656 .unwrap();
657 let second = TypeMeta::new(
658 TypeId::NAMED_ENUM as u32,
659 NO_USER_TYPE_ID,
660 namespace,
661 type_name,
662 true,
663 vec![],
664 )
665 .unwrap();
666 resolver
667 .check_remote_type_meta_limit(&second, &config)
668 .unwrap();
669 }
670}