@@ -371,17 +371,38 @@ macro_rules! impl_try_parse_primitive_array {
371
371
match prop_slice. property. info {
372
372
PropertyInfo :: Array { .. } => {
373
373
// TODO: Check In and Out type and do a better type checking
374
+
375
+ // This property type has not been tested yet as I don't have a
376
+ // provider that uses it. It's possible that the buffer is not
377
+ // aligned correctly, which would cause this to fail.
374
378
let size = std:: mem:: size_of:: <$T>( ) ;
379
+ let align = std:: mem:: align_of:: <$T>( ) ;
380
+
375
381
if prop_slice. buffer. len( ) % size != 0 {
376
382
return Err ( ParserError :: LengthMismatch ) ;
377
383
}
384
+
378
385
let count = prop_slice. buffer. len( ) / size;
386
+
387
+ if prop_slice. buffer. as_ptr( ) as usize % align != 0 {
388
+ return Err ( ParserError :: PropertyError (
389
+ "buffer alignment mismatch" . into( )
390
+ ) ) ;
391
+ }
392
+
393
+ if size. checked_mul( count) . is_none( ) || ( size * count) > isize :: MAX as usize {
394
+ return Err ( ParserError :: PropertyError (
395
+ "size overflow" . into( )
396
+ ) ) ;
397
+ }
398
+
379
399
let slice = unsafe {
380
400
std:: slice:: from_raw_parts(
381
401
prop_slice. buffer. as_ptr( ) as * const $T,
382
402
count,
383
403
)
384
404
} ;
405
+
385
406
Ok ( slice)
386
407
}
387
408
_ => Err ( ParserError :: InvalidType ) ,
@@ -447,19 +468,26 @@ impl private::TryParse<String> for Parser<'_, '_> {
447
468
) ) ;
448
469
}
449
470
450
- let mut wide = unsafe {
451
- std:: slice:: from_raw_parts (
452
- prop_slice. buffer . as_ptr ( ) as * const u16 ,
453
- prop_slice. buffer . len ( ) / 2 ,
454
- )
455
- } ;
471
+ // std::slice::from_raw_parts requires a pointer to be aligned, but we can't
472
+ // guarantee that the buffer is aligned. In testing, I found that the buffer
473
+ // is in fact never aligned appropriately, so a cheap workaround is to copy
474
+ // the buffer into a new Vec<u16> and use that as the source for the slice
475
+ // until we can find a better solution.
476
+ let mut aligned_buffer = Vec :: with_capacity ( prop_slice. buffer . len ( ) / 2 ) ;
477
+ for chunk in prop_slice. buffer . chunks_exact ( 2 ) {
478
+ let part = u16:: from_ne_bytes ( [ chunk[ 0 ] , chunk[ 1 ] ] ) ;
479
+ aligned_buffer. push ( part) ;
480
+ }
481
+
482
+ let mut wide = aligned_buffer. as_slice ( ) ;
456
483
457
484
match wide. last ( ) {
458
485
// remove the null terminator from the slice
459
486
Some ( c) if c == & 0 => wide = & wide[ ..wide. len ( ) - 1 ] ,
460
487
_ => ( ) ,
461
488
}
462
489
490
+ // Decode UTF-16 to String
463
491
Ok ( widestring:: decode_utf16_lossy ( wide. iter ( ) . copied ( ) ) . collect :: < String > ( ) )
464
492
}
465
493
TdhInType :: InTypeAnsiString => {
0 commit comments