MAPI icon indicating copy to clipboard operation
MAPI copied to clipboard

`Undefined array key` error in PropertyStore.php

Open S-R0 opened this issue 4 years ago • 3 comments

Getting an error in hfig/mapi/src/MAPI/Property/PropertyStore.php on line 155.

Screenshot 2021-06-03 at 11 01 21

A simple fix for now is to add a try/catch to the parseNameId function, and just skip any iterations of the foreach (str_split($propsData, 8) as $idx => $rawProp) loop that are throwing that error.

From a real use case scenario, I would much rather that any that are broken are just ignored and skipped, but the function still processes the message rather than ignoring it.

php - 8.0 hfip/mapi - 1.2.0

S-R0 avatar May 28 '21 10:05 S-R0

The code in Ruby looks like this:

props = props_obj.read.scan(/.{8}/mn).map do |str|
    flags, offset = str[4..-1].unpack 'v2'
    # the property will be serialised as this pseudo property, mapping it to this named property
    pseudo_prop = 0x8000 + offset
    named = flags & 1 == 1
    prop = if named
        str_off = str.unpack('V').first
        len = names_data[str_off, 4].unpack('V').first
        Ole::Types::FROM_UTF16.iconv names_data[str_off + 4, len]
    else
        a, b = str.unpack('v2')
        Log.debug "b not 0" if b != 0
        a
    end
    # a bit sus
    guid_off = flags >> 1
    # missing a few builtin PS_*
    Log.debug "guid off < 2 (#{guid_off})" if guid_off < 2
    guid = guids[guid_off - 2]
    [pseudo_prop, Key.new(prop, guid)]
end

It was translated into PHP as

foreach (str_split($propsData, 8) as $idx => $rawProp) {
    if (strlen($rawProp) < 8) break;

    $d      = unpack('vflags/voffset', substr($rawProp, 4));
    $flags  = $d['flags'];
    $offset = $d['offset'];

    //# the property will be serialised as this pseudo property, mapping it to this named property
    $pseudo_prop = 0x8000 + $offset;
    $named = ($flags & 1 == 1);
    $prop  = '';
    if ($named) {
        $str_off = unpack('V', $rawProp)[1];
        if (strlen($namesData) - $str_off < 4) continue; // not sure with this, but at least it will not read outside the bounds and crash
        $len = unpack('V', substr($namesData, $str_off, 4))[1];
        $data = substr($namesData, $str_off + 4, $len);
        $prop = mb_convert_encoding($data, 'UTF-8', 'UTF-16LE');
    }
    else {
        $d = unpack('va/vb', $rawProp);
        if ($d['b'] != 0) {
            $this->logger->Debug("b not 0");
        }
        $prop = $d['a'];
    }

    //# a bit sus
    $guid_off = $flags >> 1;
    $guid = $guids[$guid_off - 2];

    /*$properties[] = [
        'key' => new PropertyKey($prop, $guid),
        'prop' => $pseudo_prop,
    ];*/
    $properties[$pseudo_prop] = new PropertyKey($prop, $guid);
            
}

Please check my translation.

Also check the spec https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxmsg/193c169b-0628-4392-aa51-83009be7d71f

(I believe what looks like an off-by-one issue in the decoding of the "Index and Kind Information" spec 2.2.3.1.2.1 [called "flags" and "offset" in the code] because of an indexing difference between the spec and the code.)

You apparently have with an offset of 3118 which means you have a file asking for the 1559th GUID property in the file. This is very - even absurdly - high. Suggests an invalid file. Can you provide the file?

In any case, I'd suggest:

  1. Verify the code is parsing the file as per the standard
  2. If so, make a PR to check array_key_exists($guids, $guid_off-2) and, if the array key doesn't exist, skip adding it while logging a warning

Don't submit a PR with try {} catch {} of the whole routine, I'm not going to merge that!

hfig avatar May 29 '21 09:05 hfig

Hi,

I have the same problem in case of trying to manage a outlook message with attachment:

/vendor/hfig/mapi/src/MAPI/Property/PropertyStore.php
"Undefined offset: 3116" line:155
/vendor/hfig/mapi/src/MAPI/Property/PropertyStore.php(155): yii\base\ErrorHandler->handleError()
vendor/hfig/mapi/src/MAPI/Property/PropertyStore.php(52): Hfig\MAPI\Property\PropertyStore->parseNameId()
/vendor/hfig/mapi/src/MAPI/Property/PropertyStore.php(41): Hfig\MAPI\Property\PropertyStore->load()
/vendor/hfig/mapi/src/MAPI/Message/Message.php(54): Hfig\MAPI\Property\PropertyStore->__construct()
/vendor/hfig/mapi/src/MAPI/MapiMessageFactory.php(22): Hfig\MAPI\Message\Message->__construct()
 Hfig\MAPI\MapiMessageFactory->parseMessage()

Is there any solution how to fix this?

strtob avatar Feb 26 '22 18:02 strtob

HI guys,

Does anyone find a solution for this problem by now? :-/

strtob avatar May 08 '22 14:05 strtob