ColdFusion 9: неприятная ошибка int и type=numeric?

Я только что столкнулся с поведением, которое не поддается никакой логике и потенциально может привести к серьезным проблемам, и мне интересно, это ошибка или это поведение было изменено, и каковы наилучшие способы обойти эту проблему? Если это ошибка, есть ли исправление?

Вот два странных поведения, которые вместе представляют угрозу целостности данных любой системы.

  1. int('1 2') -> 41276
  2. isValid('numeric', '1 2') -> true

Почему? Ну посмотрим...

<cffunction name="deleteSomething" access="public" returntype="void">
    <cfargument name="somethingId" type="numeric" required="yes">

    <cfquery datasource="#dsn()#">
        DELETE
        FROM Something
        WHERE id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.somethingId#">;   
    </cfquery>

</cffunction>


<cfset deleteSomething('1 2')>

Здесь проверка аргументов type="numeric" (которая, возможно, основана на том же алгоритме, что и isValid?) не срабатывает с '1 2'. Хуже того, cfqueryparam cfsqltype="cf_sql_integer", похоже, использует int для преобразования значения, которое в конечном итоге будет 41276.

Другими словами, deleteSomething('1 2') удалит объект с идентификатором 41276 вместо того, чтобы генерировать исключение, поскольку значение 1 2 явно не является числовым.

Теперь единственное исправление, о котором я подумал, - это выполнить дополнительную проверку аргумента с использованием isValid('integer', ... или регулярного выражения, но это настоящая боль, и, кроме того, я никогда не понимал, почему они не реализовали type="integer"?

Очевидно, я также всегда делал ложное предположение, что cfqueryparam type="cf_sql_integer" подтвердит, что переданное значение является допустимым целым числом.

РЕДАКТИРОВАТЬ:

Кажется, что даже isvalid('integer', ... также ненадежен, как мы можем видеть в
Why isvalid(integer, 1,5) = ДА?

РЕДАКТИРОВАТЬ2:

Я знаю, что могу добавить дополнительную проверку аргументов для каждого ожидаемого целочисленного аргумента в каждой функции, однако в моем случае это потребует исправления огромной базы кода, а также очень подвержено ошибкам. Это также делает встроенную проверку аргумента совершенно бесполезной в этом случае.

Я предпочел бы решение, в котором я мог бы создать и применить неофициальный патч. Это реальный вариант? Если это так, я хотел бы, чтобы меня указали в правильном направлении.

EDIT3: это не решает всех проблем, но в CF11 добавлена ​​поддержка strictNumberValidation на уровне приложения.

«Начиная с ColdFusion 11, эта функция оценивается на более строгой основе. Установка этого значения в false приводит к тому, что функция isValid ведет себя по-старому. Этот параметр влияет на теги cfargument, cfparam и cfform везде, где используется целочисленная и числовая проверка. этот параметр, проверка также отражается на этих тегах».


person plalx    schedule 02.10.2013    source источник
comment
Повторяющийся вопрос: stackoverflow.com/questions/11535979/why -isvalidinteger-1-5-yes похоже, Adobe не исправляет это.   -  person Jarede    schedule 02.10.2013
comment
@Jarede, спасибо за ссылку. Однако я считаю, что мой вопрос подчеркивает еще несколько аномалий и не является дубликатом.   -  person plalx    schedule 02.10.2013
comment
если вы посмотрите на соответствующий вопрос SO, он в значительной степени ответит на все, что вы подняли. подробности см. в ответе @Mike Causer.   -  person Jarede    schedule 02.10.2013
comment
Я обнаружил, что проверка isValid(variablename) для имени переменной ColdFusion также игнорирует пробелы в CF8, 9 и 10. isValid(variablename, abc) оценивается как действительное имя переменной ColdFusion, даже если есть начальные и конечные пробелы.   -  person James Moberg    schedule 02.10.2013
comment
Функция isDate() ненамного лучше. Возвращает true на 31 апреля.   -  person Dan Bracuk    schedule 02.10.2013
comment
@Jarede Это не тот ответ, который я ищу. Я все еще надеюсь, что есть лучшие альтернативы, о которых я еще не подумал и не описал в проблематике.   -  person plalx    schedule 02.10.2013


Ответы (2)


Это вариация на эту тему из другого вопроса. Посмотрите этот код (или запустите его на cflive.net):

<cfscript>
s = "1 2";
i = int(s);
v = isValid("numeric", s);
d = createOdbcDate(s);
writeDump([s,i,v,d]);
</cfscript>

s преобразуется в 41276 при вызове int(), и при использовании его в качестве входных данных для createOdbcDate() мы получаем:

January, 02 2013 00:00:00 +0000

Таким образом, "1 2" интерпретируется как "m d" с подразумеваемым годом текущего года.

Что совсем глупо. Но вот.

person Adam Cameron    schedule 02.10.2013
comment
Есть ли способ создать и применить неофициальный патч? В данном случае такое поведение делает проверку встроенных аргументов совершенно бесполезной. - person plalx; 02.10.2013
comment
@JamesMohler, не совсем так. Проблема заключается в том, чтобы исправить чрезвычайно огромную кодовую базу и ненужные накладные расходы, связанные с выполнением дополнительной проверки типов для каждого ожидаемого целочисленного аргумента. Я бы определенно предпочел решить проблему в ее основе. - person plalx; 02.10.2013
comment
@AdamCameron Не могли бы вы взглянуть на мой первый комментарий? - person plalx; 13.10.2013
comment
Нет, я не знаю способа неофициально исправить ColdFusion. Что касается того, как вы могли бы скорректировать свой подход, чтобы смягчить его, нам нужно понять, как вы стали использовать такую ​​​​строку так, как вы (что кажется немного странным, TBH). Возможно, новый вопрос здесь, с более подробной информацией? - person Adam Cameron; 14.10.2013
comment
@AdamCameron Я не использую строку, и API примера предназначен для приема числовых значений. Однако из-за этой ошибки, если разработчик совершит ошибку и передаст что-то вроде '1 2', CF не будет жаловаться, и это будет довольно сложно отладить. Следовательно, это делает встроенную проверку аргументов довольно бесполезной в этом случае. - person plalx; 25.08.2014
comment
@plalx: '1 2' является строкой. - person Adam Cameron; 25.08.2014
comment
@AdamCameron Это моя точка зрения ... не уверен, что ты пытаешься сказать? Я имею в виду, что если бы в системе была ошибка и каким-то образом подобная строка была бы передана в API, как указано выше, CF не жаловался бы, и функция выполнялась бы правильно, поскольку строка была бы преобразована в целое число с помощью cfqueryparam . Такую ошибку было бы довольно трудно найти из-за неспособности CF выполнять свою работу должным образом. Совершенно невероятно, что для этого нет решения, кроме повторной проверки аргумента в теле функции. - person plalx; 25.08.2014

Вы можете использовать регулярные выражения, чтобы узнать, есть ли какие-либо нечисловые символы в данном поле формы:

reFind( "[^\d-]", "1 2")

Это будет соответствовать любому символу, который не является числом, а не -

Если вы хотите проверить только положительные числа, вы можете использовать

reFind( "[^\d]", "1 2")    

Если это возвращает true, у вас нет целого числа.

person Scott Stroz    schedule 02.10.2013
comment
Спасибо, но я уже указал это решение в вопросе. - person plalx; 02.10.2013
comment
--0---0-- не является числом; проверку того, является ли ввод целым числом со знаком с регулярным выражением, лучше выполнить с помощью NOT refind( "^-?\d+$" , input ) ... для второго, \D - это ярлык для [^\d] - person Peter Boughton; 03.10.2013
comment
Хорошая точка зрения. Это научит меня не писать регулярное выражение слишком быстро. - person Scott Stroz; 03.10.2013