AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 05.08.2010, 15:49   #1  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Thumbs down Как завалить AOS AX 2009
Версия ядра клиента и сервера AX 2009 - 5.0.1500.2985, т.е. RU5.
Ниже приводится тестовый пример, который при вызове с клиента гарантированно валит AOS на test2():
X++:
CustTable test1(CustTable _custTableOther = null, CustGroupId _custGroupId = '')
{
    CustTable   custTable;
    ;
    if (_custTableOther)
    {
        select firstonly custTable where custTable.CustGroup == _custTableOther.CustGroup;
    }
    else
    {
        select firstonly custTable where custTable.CustGroup == _custGroupId;
    }
    return custTable;
}
CustTable test2(CustTable _custTableOther = null, CustGroupId _custGroupId = '')
{
    CustTable   custTable;
    ;
    select firstonly custTable
        where   (   (   _custTableOther
                    &&  custTable.CustGroup == _custTableOther.CustGroup
                    )
                ||  (  !_custTableOther
                    &&  custTable.CustGroup == _custGroupId
                    )
                )
                        ;
    return custTable;
}
;
test1();
test2();
Дело, судя по всему в том, что AOS как-то некорректно пытается получить доступ к буферу _custTableOther в том случае, если в качестве него передан null. И воспроизводится это именно при вызове с клиента - при выполнении кода на сервере все отрабатывает нормально; тот же тестовый джобик можно запустить на сервер, создав для него специальный пункт меню.
Ниже приводится еще один джобик, который эвристически пытается найти схожие конструкции в коде (для ускорения запускать его лучше на сервере). При этом сравнительно часто встречаются ложные срабатывания, но в целом если удастся отловить 1-2 таких места (преимущественно в своем коде ), то уже время будет потрачено не впустую. В стандартном коде было найдено несколько "подозрительных" мест, но при попытке их эксплойта выяснилось, что они к сваливанию AOS'а не приводят. Подозрения пали на следующие методы, схожим образом использующие свои табличные параметры:
  • \Classes\SalesFormLetter\reselect - но в нем явно проверяется, что метод отрабатывает на сервере;
  • \Classes\RTax25RegTransEngine\updateTotals - здесь перед выполнением запроса идет проверка if (!_mainTrans && !_origTrans), которая неявно инициализирует оба табличных буфера;
  • \Classes\RTax25RegTransEngine_TaxRemainGoods\updateTotals - аналогично RTax25RegTransEngine
X++:
UtilEntryLevel  currentLayer;
UtilElements    utilElements;
DictMethod      dictMethod;
xRefPath        nodePath;
str             source;
str             pattern;
Set             setOfParmNameExclusions;
Set             setOfRecordParmNames;
SetEnumerator   setEnum;
boolean         currentAOLayerOnly;
Counter         cnFound;
Counter         n;
;
setOfParmNameExclusions = new Set( Types::String );
setOfParmNameExclusions.add( '_inventDimCriteria' );
setOfParmNameExclusions.add( '_inventDimParm' );
setOfParmNameExclusions.add( '_inventDimParmCriteria' );

currentLayer = currentAOLayer();
currentAOLayerOnly = Box::yesNo( strfmt( @"Искать только на слое %1?", currentLayer ), DialogButton::Yes ) == DialogButton::Yes;
while select utilElements
    where   (   utilElements.recordType   == UtilElementType::ClassInstanceMethod
            ||  utilElements.recordType   == UtilElementType::ClassStaticMethod
            ||  utilElements.recordType   == UtilElementType::TableInstanceMethod
            ||  utilElements.recordType   == UtilElementType::TableStaticMethod
            )
        &&  (  !currentAOLayerOnly
            ||  utilElements.utilLevel    == currentLayer
            )
{
    dictMethod = new DictMethod( utilElements.recordType, utilElements.parentId, utilElements.name );
    if (    dictMethod
        &&  dictMethod.compiledOk()
        &&  dictMethod.parameterCnt() > 0
       )
    {
        setOfRecordParmNames = null;
        for (n = 1; n <= dictMethod.parameterCnt(); n++)
        {
            if (        dictMethod.parameterType( n )   == Types::Record
                &&  (   utilElements.utilLevel          == currentLayer
                    || !setOfParmNameExclusions.in( dictMethod.parameterName( n ) )
                    )
               )
            {
                if (!setOfRecordParmNames)
                {
                    setOfRecordParmNames = new Set( Types::String );
                }
                setOfRecordParmNames.add( dictMethod.parameterName( n ) );
            }
        }
        if (setOfRecordParmNames && !setOfRecordParmNames.empty())
        {
            source = conpeek( utilElements.source, 1 );
            setEnum = setOfRecordParmNames.getEnumerator();
            while (setEnum.moveNext())
            {
                pattern = strfmt( @"select [^;{]+ where [^;{]*[^a-z0-9_;{.]%1[^a-z0-9_.]", setEnum.current() );
                if (match( pattern, source ))
                {
                    nodePath = xUtilElements::getNodePathRough( utilElements );
                    info( strfmt( @"%1 - %2 (%3)", nodePath, setEnum.current(), utilElements.utilLevel ), '', SysInfoAction_Editor::newOpen( nodePath ) );
                    break;
                }
            }
        }
    }
}
За это сообщение автора поблагодарили: AlGol (2), Vadik (1), Hyper (1), Logger (12).
Старый 05.08.2010, 17:46   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Добавлю свои 5 копеек.
Мне тоже удалось свалить аос. Что очень неприятно

Как уронить. Делаем кастомизации в классе SalesFormLetter
добавляем в макрос ParmListCommonCS еще 28 параметров
Итого в нем становится 42 параметра.
После этого АОС благополучно валится на распаковке в методе \Classes\SalesFormLetter_Facture_RU\unpack
при обработке фактуры по заказу.

Причем делает это зараза по подлому, если идти по шагам в отладчике то не валится, а если без отладчика то валится с ошибкой "Ошибка 25 в сценарии SQL"

Лечили так

X++:
public container pack()
{
//  return [ #CurrentVersion + #ParentVersion, #ParmList, #ParmListCommonCS ];          //-pkoz, 12.07.2010
    return [ #CurrentVersion + #ParentVersion, [ #ParmList ], [ #ParmListCommonCS ] ];  //+pkoz, 12.07.2010
}

X++:
public boolean unpack(container _packedClass)
{
    Integer version = conpeek(_packedClass, 1);
    // pkoz, 12.07.2010 -->
    container       conParmList;
    container       conParmListCommonCS;
    // pkoz, 12.07.2010 <--

    ;
    switch (version)
    {
        case #CurrentVersion + #ParentVersion :
            // pkoz, 12.07.2010 -->
//          [ version, #ParmList, #ParmListCommonCS ] = _packedClass;
            [ version, conParmList, conParmListCommonCS ] = _packedClass;
            [ #ParmList ] = conParmList;
            [ #ParmListCommonCS ] = conParmListCommonCS;
            // pkoz, 12.07.2010 <--
            break;
        default :
            return false;
    }

    return true;
}
Т.е. разбили перечень параметров на несколько контейнеров.

В 3-й аксапте не припомню случая чтобы аос падал. Клиент - сколько угодно, а АОС никогда. Получается что в 2009-й аксапте стабильность работы на порядок хуже. Если эти падения не исправить, то и переходить на неё пожалуй не стоит.

AX 2009 - 5.0.1500.2985, Application RU5

Последний раз редактировалось Logger; 05.08.2010 в 18:01.
За это сообщение автора поблагодарили: aidsua (2), gl00mie (2).
Старый 05.08.2010, 19:59   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Предлагаю устроить соревнование, кто найдет больше способов завалить AOS
Старый 05.08.2010, 20:18   #4  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,909 / 5730 (197) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
У нас вчера падало при попытке исполнения следующего кода:
X++:
while select    vInventBatch3
        join            vInventDim
        where           vInventBatch3.EraIsvInventDimId == vInventDim.inventDimId
                        &&
                        vInventDim.InventSiteId == vSiteId
                        &&
                        vInventDim.InventLocationId == vInventLocationId
        join            vInventBatchPrice2
        where         vInventBatchPrice2 &&
                         vInventBatchPrice2.inventBatchId == vInventBatch3.inventBatchId
                        &&
                        vInventBatchPrice2.itemId == vInventBatch3.itemId
        {
            ..
        }
Каким-то макаром компилятор пропустил конструкцию 'join table where table && table.field==constant', но сервер во время исполнения умирал выдавая на рабочую станцию сообщение типа "Internal error number 174 found in script".

Аналогичная ситуация была когда программист написал что-то типа:
Select table1
where table1.field1==constant || (table2 && table1.field==table2.field). Хотя здесь я точную форму запроса-убийцы не помню. Идея состояла в том, что сервер похоже что пытался table2 как-то засунуть в сгенерированный SQL-запрос, но сходил с ума и падал. Сообщение было таким-же. Вылечили заменив вторую половину условия на (table2.recid!=0 && table1.field==table2.field).
Справедливости ради, замечу что у нас не очень свежее ядро (примерно февральское).
Старый 05.08.2010, 20:26   #5  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от fed Посмотреть сообщение
Аналогичная ситуация была когда программист написал что-то типа:
X++:
Select table1 where table1.field1==constant || (table2 && table1.field==table2.field).
Вылечили заменив вторую половину условия на (table2.recid!=0 && table1.field==table2.field)
Приведенный запрос - именно то, с чего началась тема! Если в select проверяется табличный буфер на "непустоту", а буфер на самом деле совсем пустой (null), и все это работает с клиента, то АОС валится на раз. И лечится как раз аналогично - переделкой проверки с буфера целиком на какое-то из его полей.
Старый 05.08.2010, 22:07   #6  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,909 / 5730 (197) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Приведенный запрос - именно то, с чего началась тема! Если в select проверяется табличный буфер на "непустоту", а буфер на самом деле совсем пустой (null), и все это работает с клиента, то АОС валится на раз. И лечится как раз аналогично - переделкой проверки с буфера целиком на какое-то из его полей.
Не уверен. Там все на сервере работало. Вообще после того как я по неформальным каналам спросил знакомых в микрософте, они там выковырали описание внутренней ошибки 174, типа это означает "Какая-то фигня в выражении where". То есть - мне кажется что там все-таки сервер пытался сгенерить именно select с table2, но накрывался при попытке найти подходящее место.
Старый 05.08.2010, 22:14   #7  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от fed Посмотреть сообщение
Не уверен. Там все на сервере работало.
Зачтено

Считаем это другим случаем завала АОСА.
Счет в серии 1:1:1

Кто больше ?
Старый 05.08.2010, 22:38   #8  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от fed Посмотреть сообщение
То есть - мне кажется что там все-таки сервер пытался сгенерить именно select с table2, но накрывался при попытке найти подходящее место.
Что больше всего напрягает в этой ситуации - почему сервер накрывается ? Ну отваливался бы рабочий поток с одной сессией пользователя и все, так ведь аос целиком ложится!
В 3-ке, например, при попытке распаковать на сервере наследник RunBaseBatch-а из кривого контейнера, клиент отваливался, а серверу хоть бы что , несмотря на то что код исполнялся на сервере.
Старый 06.08.2010, 11:34   #9  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Logger Посмотреть сообщение
Что больше всего напрягает в этой ситуации - почему сервер накрывается ? Ну отваливался бы рабочий поток с одной сессией пользователя и все, так ведь аос целиком ложится!
Мне кажется, AOS просто не ловит соответствующие исключения, а раз так, то возникают они где-то там, где он не ожидает их словить. Вспоминается, как он валился однажды - при этом в eventlog писалось (виндой, а не самим AOS'ом) следующее:
Код:
Faulting application name: Ax32Serv.exe, version: 5.0.1500.2985, time stamp: 0x4c29d4fc
Faulting module name: Ax32Serv.exe, version: 5.0.1500.2985, time stamp: 0x4c29d4fc
Exception code: 0xc0000005
Fault offset: 0x0000000000650359
Faulting process id: 0x834
Faulting application start time: 0x01cb21cd511ff28c
Что примечательного в этом сообщении? А то, что виртуальный адрес 0x0000000000650359 находится посреди процессорной инструкции - вблизи него исполняемый код выглядит так:
Код:
.00000000`00650355: 4084FF     test  dil,dil
.00000000`00650358: 7411       jz   .00065036B
.00000000`0065035A: 488903     mov   [rbx],rax
.00000000`0065035D: 488B4630   mov   rax,[rsi][030]
.00000000`00650361: 483B18     cmp   rbx,[rax]
.00000000`00650364: 7517       jnz  .00065037D
т.е. по адресу 0x0000000000650358 начинается двухбайтовая инструкция условного перехода. Если же начать смотреть с адреса 0x0000000000650359, то увидим совсем левый код:
Код:
.00000000`00650359: 114889     adc  [rax][-077],ecx
.00000000`0065035C: 03488B     add  ecx,[rax][-075]
.00000000`0065035F: 4630483B   xor  [rax][03B],r9b
.00000000`00650363: 187517     sbb  [rbp][017],dh
Т.е. управление перешло по левому адресу (так совпало, что в сегмент кода, а могло бы куда угодно). Отсюда вывод: либо у AOS'а разрушился стек, либо он криво инициализировал какие-то структуры в памяти, используемые для передачи управления. При таком раскладе не удивительно, что он валится целиком, а не просто отстреливает одну сессию, как в трешке.
За это сообщение автора поблагодарили: aidsua (2), Corel (1).
Старый 06.08.2010, 11:38   #10  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Цитата:
Сообщение от Logger Посмотреть сообщение
почему сервер накрывается ?
Потому что криво написали обработку исключений на сервере.
Старый 06.08.2010, 19:49   #11  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от _scorp_ Посмотреть сообщение
Потому что криво написали обработку исключений на сервере.


Ну это понятно.
Вопрос почему такое допустили. Неприятно когда у тебя в системе одновременно вылетает 150 юзеров.
Старый 19.08.2010, 13:39   #12  
Link is offline
Link
Британский учённый
Аватар для Link
Соотечественники
 
568 / 523 (19) +++++++
Регистрация: 25.11.2005
Адрес: UK
Записей в блоге: 9
Цитата:
Сообщение от Logger Посмотреть сообщение
В 3-й аксапте не припомню случая чтобы аос падал. Клиент - сколько угодно, а АОС никогда. Получается что в 2009-й аксапте стабильность работы на порядок хуже. Если эти падения не исправить, то и переходить на неё пожалуй не стоит.

AX 2009 - 5.0.1500.2985, Application RU5
У меня недавно был чп с AOSом в 4-ке. Казалось бы простая модификация EDT с увеличением числа элементов массива ложила AOS. Удалось решить только удалением всех связанных объектов с нижних слоев и создание их заново на USR. Очень странно это выглядело, АОS падал мгновенно при попытке синхронизации. Причем сообщение об ошибке ничего конкретного не говорило.
Старый 20.12.2010, 18:11   #13  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
На ядре 5.0.1500.3966 (hotfix, вышедший после RU6) ошибка все еще воспроизводится...
Старый 22.12.2010, 08:21   #14  
Alexius is offline
Alexius
Участник
Аватар для Alexius
 
461 / 248 (9) ++++++
Регистрация: 13.12.2001
Цитата:
Сообщение от gl00mie Посмотреть сообщение
На ядре 5.0.1500.3966 (hotfix, вышедший после RU6) ошибка все еще воспроизводится...
А можно поподробнее об этом фиксе ?
Старый 23.12.2010, 10:40   #15  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Фикс касается работы с Oracle (хотя судя по разнице в номерах сборки там еще много чего исправлено), подробности уже описаны в теме DAX 2009 некорректный SPID в форме активных пользователей
Старый 27.12.2010, 13:02   #16  
ansoft is offline
ansoft
Участник
Аватар для ansoft
 
123 / 37 (2) +++
Регистрация: 20.10.2005
Только что уронил АОС job-ом:

X++:
static void Job479(Args _args)
{
    ledgerTrans LedgerTrans;
    int         i;
    ;
    info(strfmt('Начало %1', time2str(timenow(),1,1)));
    while select accountnum, crediting, dimension[1], dimension[2], dimension[4], dimension[6], sum(amountmst) from ledgertrans
    index hint ACDate
    group by accountnum, crediting, dimension[1], dimension[2], dimension[4], dimension[6]
    where ledgerTrans.accountnum like '20*'
            && ledgerTrans.transdate >= 01\01\2009
            && ledgerTrans.transdate <= 31\03\2009
    {
        i++;
    }
     info(strfmt('Окончания в %1, выбрано записей %2', time2str(timenow(),1,1), i));

}
JOB компилируется на ура, однако у нас доступно только 5 аналитик и обратиться к
dimension[6] никак нильзя... в результате быстрая смерть АОСа (RU6).
За это сообщение автора поблагодарили: Logger (1), aidsua (1).
Старый 01.02.2011, 19:09   #17  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Еще один рецепт, как завалить AOS либо свалить клиента (в зависимости от того, где будет выполняться код):
X++:
Dimension   dim;
anytype     val = dim;
Выловлено на последовательной обработке полей таблицы по fieldId, ядро 5.0.1500.3968. Проверил в 3.0: там при выполнении такого кода на клиенте последний тоже валится, но если код выполнять на сервере, то он просто отстреливает сессию, а сам продолжает работать.
За это сообщение автора поблагодарили: Pustik (1), Logger (5).
Старый 02.02.2011, 07:15   #18  
TasmanianDevil is offline
TasmanianDevil
Мрачный тип
Аватар для TasmanianDevil
Злыдни
 
886 / 389 (14) ++++++
Регистрация: 24.01.2005
Адрес: Томск
Страшные вещи Вы говорите ...
У нас корячится в перспективе переход на 2009, но после вышеописанных случаев - меня терзают смутные сомнения
__________________
Мы летаем, кружимся, нагоняем ужасы ...
Старый 02.02.2011, 10:58   #19  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Да ладно. Неприятно, но некритично.
3-ка же тоже сессии отстреливала и ничего - жили.
Старый 16.02.2011, 16:57   #20  
AX2009
Гость
 
n/a
шестерка тоже умирает.. напишите в микросовт, зачем плакаться на форумах?

а вот тут уже не умирает
X++:
Dimension   dim;
[COLOR=blue]anytype[/COLOR]     val = dim;
Теги
aoc, aos, ax2009, crash, баг, ошибка, падает, ядро

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
mbsturk: Ax 2009 Rollup 4 Version Checker Blog bot DAX Blogs 0 29.04.2010 17:05
emeadaxsupport: List of fixes that improve performance of certain features in Dynamics AX 2009 Blog bot DAX Blogs 0 13.10.2009 19:06
gatesasbait: Dynamics AX 2009 SSRS and SSAS Integration Tips Blog bot DAX Blogs 3 09.07.2009 13:07
axStart: Microsoft Dynamics AX 2009 Hot Topics Web Seminar Series Blog bot DAX Blogs 0 06.08.2008 12:05
Arijit Basu: AX 2009 - Quick Overview Blog bot DAX Blogs 4 19.05.2008 14:47

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 22:42.