override method_param/field name if it collides

This commit is contained in:
Janis 2023-06-26 10:51:36 +02:00
parent 9511f49163
commit 1ab11164d3
3 changed files with 72 additions and 8 deletions

View file

@ -411,13 +411,13 @@ pub mod rust {
struct_name: &str, struct_name: &str,
method: &ClassMethod, method: &ClassMethod,
) -> anyhow::Result<(TokenStream, TokenStream)> { ) -> anyhow::Result<(TokenStream, TokenStream)> {
let method_name = canonicalize_name(&method.name); let method_name = canonicalize_name(&method.unique_name());
let parameters = method let parameters = method
.parameters .parameters
.iter() .iter()
.map(|parameter| { .map(|parameter| {
let name = canonicalize_name(&parameter.name); let name = canonicalize_name(&parameter.unique_name());
let type_name = self.type_name(&parameter.ty)?; let type_name = self.type_name(&parameter.ty)?;
anyhow::Ok((parameter, name, type_name)) anyhow::Ok((parameter, name, type_name))
@ -611,7 +611,7 @@ pub mod rust {
.fields .fields
.iter() .iter()
.map(|field| { .map(|field| {
let name = canonicalize_name(&field.name); let name = canonicalize_name(&field.unique_name());
let ty = self.type_name(&field.ty)?; let ty = self.type_name(&field.ty)?;
anyhow::Ok((field, name, ty)) anyhow::Ok((field, name, ty))

View file

@ -8,6 +8,7 @@ use ron::ser::PrettyConfig;
use crate::global_tables::objects::GOBJECTS; use crate::global_tables::objects::GOBJECTS;
use crate::sdk::repr::*; use crate::sdk::repr::*;
use crate::util::DedupIter;
use crate::v2_types::{ use crate::v2_types::{
any_type::{self, AnyField, AnyObject, AnyProperty, AnyStruct}, any_type::{self, AnyField, AnyObject, AnyProperty, AnyStruct},
traits::{ traits::{
@ -238,6 +239,28 @@ impl Class {
}, },
); );
let fields = fields
.into_iter()
.dedup_with_by(
|n, field| ClassField {
override_name: Some(format!("{}{}", field.name, n)),
..field
},
|field: &ClassField| -> String { field.name.clone() },
)
.collect();
let methods = methods
.into_iter()
.dedup_with_by(
|n, field| ClassMethod {
override_name: Some(format!("{}{}", field.name, n)),
..field
},
|field: &ClassMethod| -> String { field.name.clone() },
)
.collect();
(fields, methods) (fields, methods)
} }
@ -257,14 +280,16 @@ impl Class {
impl ClassField { impl ClassField {
pub fn from_uprop(prop: UProperty) -> anyhow::Result<Self> { pub fn from_uprop(prop: UProperty) -> anyhow::Result<Self> {
let name = prop
.name()
.get_name()
.context("failed to retrieve field name")?;
Ok(Self { Ok(Self {
offset: *prop.offset() as u32, offset: *prop.offset() as u32,
size: *prop.element_size() as u32, size: *prop.element_size() as u32,
flags: *prop.property_flags(), flags: *prop.property_flags(),
name: prop override_name: None,
.name() name,
.get_name()
.context("failed to retrieve field name")?,
ty: resolve_type(prop).context("failed to get field type")?, ty: resolve_type(prop).context("failed to get field type")?,
}) })
} }
@ -288,11 +313,21 @@ impl ClassMethod {
_ => None, _ => None,
}) })
.map(|prop| ClassField::from_uprop(prop)) .map(|prop| ClassField::from_uprop(prop))
.collect::<anyhow::Result<Vec<_>>>()?; .collect::<anyhow::Result<Vec<_>>>()?
.into_iter()
.dedup_with_by(
|n, field| ClassField {
override_name: Some(format!("{}{}", field.name, n)),
..field
},
|field: &ClassField| -> String { field.name.clone() },
)
.collect();
Ok(ClassMethod { Ok(ClassMethod {
name, name,
full_name, full_name,
override_name: None,
flags: *func.function_flags(), flags: *func.function_flags(),
parameters: params, parameters: params,
}) })
@ -359,6 +394,14 @@ impl Package {
.context("not actually a package object")?, .context("not actually a package object")?,
types, types,
dependencies, dependencies,
name: self
.package_object
.get_name()
.context("failed to get package object name.")?,
full_name: self
.package_object
.get_full_name()
.context("failed to get package object name.")?,
}) })
} }
} }

View file

@ -55,6 +55,8 @@ pub struct Package {
pub struct ProcessedPackage { pub struct ProcessedPackage {
/// the package object ref. /// the package object ref.
pub package_object: PackageRef, pub package_object: PackageRef,
pub name: String,
pub full_name: String,
/// all types extracted from this package referenced by their `ObjectRef`. /// all types extracted from this package referenced by their `ObjectRef`.
pub types: BTreeMap<ObjectRef, UnrealType>, pub types: BTreeMap<ObjectRef, UnrealType>,
/// All other packages that types in this package depend on directly. /// All other packages that types in this package depend on directly.
@ -142,6 +144,7 @@ pub struct ClassField {
pub offset: u32, pub offset: u32,
pub size: u32, pub size: u32,
pub name: String, pub name: String,
pub override_name: Option<String>,
pub flags: EPropertyFlags, pub flags: EPropertyFlags,
pub ty: Type, pub ty: Type,
} }
@ -166,11 +169,19 @@ impl ClassField {
pub fn is_rep(&self) -> bool { pub fn is_rep(&self) -> bool {
!self.flags.contains(EPropertyFlags::RepSkip) !self.flags.contains(EPropertyFlags::RepSkip)
} }
pub fn unique_name(&self) -> &str {
self.override_name
.as_ref()
.map(|s| s.as_str())
.unwrap_or(self.name.as_str())
}
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct ClassMethod { pub struct ClassMethod {
pub name: String, pub name: String,
pub override_name: Option<String>,
pub full_name: String, pub full_name: String,
pub flags: EFunctionFlags, pub flags: EFunctionFlags,
pub parameters: Vec<ClassField>, pub parameters: Vec<ClassField>,
@ -180,13 +191,23 @@ impl ClassMethod {
pub fn is_static(&self) -> bool { pub fn is_static(&self) -> bool {
self.flags.contains(EFunctionFlags::Static) self.flags.contains(EFunctionFlags::Static)
} }
pub fn is_native(&self) -> bool { pub fn is_native(&self) -> bool {
self.flags.contains(EFunctionFlags::Native) self.flags.contains(EFunctionFlags::Native)
} }
/// this function is replicated to the server, might be exploitable. /// this function is replicated to the server, might be exploitable.
pub fn is_net_server(&self) -> bool { pub fn is_net_server(&self) -> bool {
self.flags.contains(EFunctionFlags::NetServer) self.flags.contains(EFunctionFlags::NetServer)
} }
pub fn unique_name(&self) -> &str {
self.override_name
.as_ref()
.map(|s| s.as_str())
.unwrap_or(self.name.as_str())
}
pub fn out_params(&self) -> Vec<&ClassField> { pub fn out_params(&self) -> Vec<&ClassField> {
self.parameters self.parameters
.iter() .iter()