Re[15]: количество наследников
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.12.21 12:44
Оценка:
Здравствуйте, Sharov, Вы писали:
S>А что мешает с появлением нового типа посмотреть от кого он наследуется, и обновить соотв. структуры?
Эмм, какие именно структуры? Речь идёт о JIT-оптимизациях.
Теоретически, конечно, возможно создавать таблицы вида "при компиляции метода X мы пользовались предположениями о наследниках типа Y". И, соответственно, при загрузке нового наследника Y проходить по всем методам, которые мы найдём в этой таблице, и ревертить их обратно к байт-коду.

На практике эта таблица может оказываться огромного размера, а потребуется, возможно, никогда.
Проще оборудовать спекулятивные оптимизации guard-ами — они отлавливают не только случай "мы думали, тут больше никого не будет", но и все остальные случаи изменения статистики вызовов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: количество наследников
От: Sharov Россия  
Дата: 20.12.21 16:50
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Sharov, Вы писали:

S>>А что мешает с появлением нового типа посмотреть от кого он наследуется, и обновить соотв. структуры?
S>Эмм, какие именно структуры? Речь идёт о JIT-оптимизациях.

Ну какие данные rt держит для соотв. типов и т.п. вещи? jit я тоже отношу к rt.

S>Теоретически, конечно, возможно создавать таблицы вида "при компиляции метода X мы пользовались предположениями о наследниках типа Y". И, соответственно, при загрузке нового наследника Y проходить по всем методам, которые мы найдём в этой таблице, и ревертить их обратно к байт-коду.


Ну да, типа того.

S>На практике эта таблица может оказываться огромного размера, а потребуется, возможно, никогда.

S>Проще оборудовать спекулятивные оптимизации guard-ами — они отлавливают не только случай "мы думали, тут больше никого не будет", но и все остальные случаи изменения статистики вызовов.

А это что за зверь?
Кодом людям нужно помогать!
Re[2]: Новогодний сюрприз от Apache
От: serb Россия  
Дата: 20.12.21 21:20
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Somescout, Вы писали:


N>https://arstechnica.com/information-technology/2021/12/patch-fixing-critical-log4j-0-day-has-its-own-vulnerability-thats-under-exploit/


N>М — мастерство. --


ПОмоему заголово не соответствует содержание, новый патч не вносил новых ошибок, он не до конца исправил старые.
Re[14]: Новогодний сюрприз от Apache
От: · Великобритания  
Дата: 20.12.21 22:11
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Это и любопытно... А где можно кишки этого дела найти? Я что-то не смог нагуглить сходу.

S>Вы уже прочитали статью на Хабре, на которую я ссылался? https://habr.com/ru/post/590069/
Ой, пропустил. Прочитал, интересно. Т.е. они захватывают не только значения, но и имена параметров. Т.е. можно не писать ("a={}", a), а просто ($"{a}). С другой стороны, смотрю я на реальный код и обычно вижу ("Fooing bar moo boo id={}, state={}", someStuff.getRequestId(), someStuff.getState())...

S>>>Судя по результатм бенчмарка, самый быстрый способ — всё же оборачивать логгер в if.

S>·>Посмотри внимательнее "conditional check is useless here": тайминги getTimeWithCheck=1.030 vs getTimeWithoutCheck=1.140 — в пределах погрешности измерения.
S>Ну, 10% это всё же 10%.
Ты на столбик error ещё обращай внимание, мерять наносекундные величины точно не получается. А то внезапно получится, что условие и ускорять может: getTimeWithCheckBenchLocal=1.608 getTimeWithoutCheckLocal=1.613. Вообще там какой-то странный тест. Я написал свой, java 11. И у меня внезапно с проверкой получается всё примерно одинаково (Код ниже):
Benchmark                      Mode  Cnt  Score   Error  Units
LoggerPerf.baseline            avgt    4  2.346 ± 0.021  ns/op
LoggerPerf.globalWithCheck     avgt    4  4.078 ± 0.139  ns/op
LoggerPerf.globalWithoutCheck  avgt    4  4.076 ± 0.022  ns/op
LoggerPerf.localWithCheck      avgt    4  3.985 ± 0.035  ns/op
LoggerPerf.localWithoutCheck   avgt    4  4.078 ± 0.007  ns/op


S>·>Вот мне и неясно чем $"Some message {data} more" поможет, кроме как если компилятор делает какую-то специальную магию, так что проверка уровня происходит до интерполяции. Неясно как фича интерполяции взаимодействует с фичей проверки уровня логгера.

S>Всё же прочтите статью. После этого можно будет попробовать её разбрать на sharplab.io и посмотреть, что за код генерируется в итоге.
S>Разница между C# и интерполяцией из log2j2 не в поведении при отключении логгирования, а в безопасности.
Это криворукость конкретно log4j. В том же logback (альтернативная реализация того же slf4j api) такого идиотизма нет.

  LoggerPerf
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class LoggerPerf
{
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerPerf.class);
    private final Logger logger = LoggerFactory.getLogger(LoggerPerf.class);
    private volatile UUID p1 = UUID.randomUUID();

    @Benchmark
    public long baseline() {
        final UUID p1 = this.p1;
        return p1.getLeastSignificantBits();
    }

    @Benchmark
    public long globalWithCheck() {
        final UUID p1 = this.p1;
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("This log is {} check", p1);
        }
        return p1.getLeastSignificantBits();
    }

    @Benchmark
    public long globalWithoutCheck() {
        final UUID p1 = this.p1;
        LOGGER.trace("This log is {} check", p1);
        return p1.getLeastSignificantBits();
    }

    @Benchmark
    public long localWithCheck() {
        final UUID p1 = this.p1;
        if (logger.isTraceEnabled()) {
            LOGGER.trace("This log is {} check", p1);
        }
        return p1.getLeastSignificantBits();
    }

    @Benchmark
    public long localWithoutCheck() {
        final UUID p1 = this.p1;
        LOGGER.trace("This log is {} check", p1);
        return p1.getLeastSignificantBits();
    }

    public static void main(String[] args) throws RunnerException
    {
        Options opt = new OptionsBuilder()
                .include(LoggerPerf.class.getSimpleName())
                .forks(1)
                .warmupForks(1)
                .warmupIterations(4)
                .warmupTime(TimeValue.seconds(2))
                .measurementIterations(4)
                .measurementTime(TimeValue.seconds(2))
//                .addProfiler(GCProfiler.class)
//                .addProfiler(PausesProfiler.class)
                .build();

        new Runner(opt).run();
    }
}
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: Новогодний сюрприз от Apache
От: Cyberax Марс  
Дата: 20.12.21 22:13
Оценка: 3 (2)
Здравствуйте, Sinclair, Вы писали:

S>·>C наследованием jit в java и так хорошо справляется — он знает кол-во наследников, и если один — virtual call elimination.

S>Тут такая штука: гарантировать количество наследников может только final. В остальных случаях мы можем только констатировать, что пока другие наследники нам неизвестны.
JVM ещё с середины 90-х годов отслеживает наследников динамически, и при появлении новых разоптимизирует прямой вызов метода и заменяет на динамический. Это практически привело к тому, что final в Java ничем не помогает для ускорения.

Фактически, предвестник трассирующих JIT для JavaScript.

S>Вызов по интерфейсу — это всегда лотерея. Я в курсе про спекулятивные оптимизации в JVM, и именно про них я и писал — будет вставлен guard condition, который не нужен в дотнете.

Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.
Sapienti sat!
Re[13]: Новогодний сюрприз от Apache
От: · Великобритания  
Дата: 20.12.21 22:46
Оценка:
Здравствуйте, Cyberax, Вы писали:


S>>Вызов по интерфейсу — это всегда лотерея. Я в курсе про спекулятивные оптимизации в JVM, и именно про них я и писал — будет вставлен guard condition, который не нужен в дотнете.

C>Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.
Не очень понял, что ты имеешь в виду.
Как я понял, там ставится условный переход по типу и оптимизация опирается на branch predictor в cpu. Притом диспатчинг может даже по нескольким типам происходить. Ну и при появлении нового типа срабатывает uncommon trap, который запустит деоптимизацию.
  2.24%    1.77%    mov    0x8(%r8),%r10d         ; load coder.<classword>
  8.38%    9.45%    cmp    $0xf801040a,%r10d      ; if coder is Coder0
                    je     CODER_0                ;   jump over
  5.65%    9.22%    cmp    $0xf8012585,%r10d      ; if coder is Coder1
                    jne    SLOW_PATH              ;   not? jump to slow path
...

                  SLOW_PATH:
...
                    callq  0x00007f3dc10051a0     ; <uncommon trap>


https://shipilev.net/blog/2015/black-magic-method-dispatch/
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[13]: Новогодний сюрприз от Apache
От: Sharov Россия  
Дата: 20.12.21 23:31
Оценка: +1
Здравствуйте, Cyberax, Вы писали:

C>Это практически привело к тому, что final в Java ничем не помогает для ускорения.


А почему, если final\sealed дает гарантию отсутствия наследников?

C>Фактически, предвестник трассирующих JIT для JavaScript.


S>>Вызов по интерфейсу — это всегда лотерея. Я в курсе про спекулятивные оптимизации в JVM, и именно про них я и писал — будет вставлен guard condition, который не нужен в дотнете.

C>Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.

А как jvm в отношении виртуальности и динамичности может быть на 100% уверена?
Кодом людям нужно помогать!
Re[14]: Новогодний сюрприз от Apache
От: Sharov Россия  
Дата: 20.12.21 23:34
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Всё же прочтите статью. После этого можно будет попробовать её разбрать на sharplab.io и посмотреть, что за код генерируется в итоге.

S>Разница между C# и интерполяцией из log2j2 не в поведении при отключении логгирования, а в безопасности.

На сколько я понимаю, причина тут совсем не в интерполяции, а в lookup и jndi. Т.е. множество случаев срабатывает,
например, log.debug("${jndi://что-тотут}"), хотя у нас стоит уровень, например info, т.е. debug отключен, но
выражение "${jndi://что-тотут}" (или как там правильно, не суть) будет вычислено, т.е. интерполировано. И это,
безусловно нехорошо, но проблема в этом? Это как преподаватель в вузе хорошую метафору решения проблем безопасности
мс рассказал -- вот, дескать, есть дырка в заборе, мс берет и передвигает забор, формально на старом месте дырки нет,
а фактически... Т.е., кмк, решение проблем интерполяции это именно перенос дырки -- ну будет реже эксплуатироваться, но
дырка-то от этого никуда не денется
Кодом людям нужно помогать!
Re[17]: количество наследников
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.12.21 01:05
Оценка: 2 (1)
Здравствуйте, Sharov, Вы писали:
S>А это что за зверь?
Это мы просто втыкаем код типа
if (a.getClass() == foo)
{
//   inllined code of foo.bar()
} 
else a.bar(); // true virtual call
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Новогодний сюрприз от Apache
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.12.21 02:21
Оценка:
Здравствуйте, Cyberax, Вы писали:

S>>Вызов по интерфейсу — это всегда лотерея. Я в курсе про спекулятивные оптимизации в JVM, и именно про них я и писал — будет вставлен guard condition, который не нужен в дотнете.

C>Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.
Хм. Это интересно. В какой момент будет компилироваться новый вариант кода?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Новогодний сюрприз от Apache
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.12.21 03:42
Оценка:
Здравствуйте, ·, Вы писали:
·>Ой, пропустил. Прочитал, интересно. Т.е. они захватывают не только значения, но и имена параметров. Т.е. можно не писать ("a={}", a), а просто ($"{a}).
Это причём не коробочная реализация — там совместно работает несколько фич компилятора.
·>С другой стороны, смотрю я на реальный код и обычно вижу ("Fooing bar moo boo id={}, state={}", someStuff.getRequestId(), someStuff.getState())...
Ну, при должной обработке в логе так и будет someStuff.RequestId, someStuff.State.
·>Ты на столбик error ещё обращай внимание, мерять наносекундные величины точно не получается. А то внезапно получится, что условие и ускорять может: getTimeWithCheckBenchLocal=1.608 getTimeWithoutCheckLocal=1.613. Вообще там какой-то странный тест. Я написал свой, java 11. И у меня внезапно с проверкой получается всё примерно одинаково (Код ниже):
·>
·>Benchmark                      Mode  Cnt  Score   Error  Units
·>LoggerPerf.baseline            avgt    4  2.346 ± 0.021  ns/op
·>LoggerPerf.globalWithCheck     avgt    4  4.078 ± 0.139  ns/op
·>LoggerPerf.globalWithoutCheck  avgt    4  4.076 ± 0.022  ns/op
·>LoggerPerf.localWithCheck      avgt    4  3.985 ± 0.035  ns/op
·>LoggerPerf.localWithoutCheck   avgt    4  4.078 ± 0.007  ns/op
·>

Ок, это означает, что код logger всё же инлайнится, и повторная проверка в нём устранена.

S>>Всё же прочтите статью. После этого можно будет попробовать её разбрать на sharplab.io и посмотреть, что за код генерируется в итоге.

S>>Разница между C# и интерполяцией из log2j2 не в поведении при отключении логгирования, а в безопасности.
·>Это криворукость конкретно log4j. В том же logback (альтернативная реализация того же slf4j api) такого идиотизма нет.
Эмм, а в чём конкретно криворукость? В самой идее интерполяции, или в её реализации?
Если второе, то как logback решает проблему безопасности?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Новогодний сюрприз от Apache
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.12.21 03:44
Оценка: 1 (1)
Здравствуйте, Sharov, Вы писали:

S>На сколько я понимаю, причина тут совсем не в интерполяции, а в lookup и jndi. Т.е. множество случаев срабатывает,

S>например, log.debug("${jndi://что-тотут}"), хотя у нас стоит уровень, например info, т.е. debug отключен, но
S>выражение "${jndi://что-тотут}" (или как там правильно, не суть) будет вычислено, т.е. интерполировано.
Эмм. Если мы про java — то нет, интерполяция откладывается до вызова метода; и там, внутри, она стоит под if. Если debug отключён, то никакой интерполяции не будет.
Если мы про C# — то наличие либо отсутствие интерполяции зависит от того типа, которым обрабатывается интерполированный аргумент.
S> И это, безусловно нехорошо, но проблема в этом? Это как преподаватель в вузе хорошую метафору решения проблем безопасности
S>мс рассказал -- вот, дескать, есть дырка в заборе, мс берет и передвигает забор, формально на старом месте дырки нет,
S>а фактически... Т.е., кмк, решение проблем интерполяции это именно перенос дырки -- ну будет реже эксплуатироваться, но
S>дырка-то от этого никуда не денется

Конечно же денется. В C# невозможно подпихнуть неожиданную {} — строку так, чтобы заставить его интерполироать выражение, не предусмотренное разработчиком приложения.
То есть я безо всяких приседаний мог бы сделать
logger.debug($"Here goes my legitimate jndi call result: {jndi.Resolve("ldap:http://good.addresss"}");

и у меня бы вызов jndi прошёл.
А вот такой вот код интерполяции jndi не вызовет:
var externalParameterValue = "{jndi.Resolve(\"ldap:http://good.addresss\"}";
logger.debug($"Here goes my legitimate jndi call result:"+externalParameterValue);
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Новогодний сюрприз от Apache
От: Cyberax Марс  
Дата: 21.12.21 04:06
Оценка: 2 (1) +1
Здравствуйте, Sharov, Вы писали:

C>>Это практически привело к тому, что final в Java ничем не помогает для ускорения.

S>А почему, если final\sealed дает гарантию отсутствия наследников?
Просто не нужно.

C>>Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.

S>А как jvm в отношении виртуальности и динамичности может быть на 100% уверена?
JVM же знает какие классы были загружены. И если есть только одна загруженная реализация IInterface, то есть полная гарантия, что виртуальных вызовов не будет.
Sapienti sat!
Re[14]: Новогодний сюрприз от Apache
От: Cyberax Марс  
Дата: 21.12.21 04:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Никакого guard condition'а не будет. JVM знает все места использования девиртуализованного интерфейса, и просто скомпилирует новый вариант кода, которым заменит старый.

S>Хм. Это интересно. В какой момент будет компилироваться новый вариант кода?
Когда я это смотрел лет 10 назад, это было при инициализации второго класса, реализующего интерфейс.

От постоянной деоптимизации при запуске программы помогает то, что JVM сначала некоторое время работает в режиме интерпретации. Так что к моменту начала JIT-а уже есть некоторая уверенность, что большинство нужных классов уже загружено.
Sapienti sat!
Re[16]: Новогодний сюрприз от Apache
От: Sharov Россия  
Дата: 21.12.21 21:18
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Конечно же денется. В C# невозможно подпихнуть неожиданную {} — строку так, чтобы заставить его интерполироать выражение, не предусмотренное разработчиком приложения.

S>То есть я безо всяких приседаний мог бы сделать
S>
S>logger.debug($"Here goes my legitimate jndi call result: {jndi.Resolve("ldap:http://good.addresss"}");
S>

S>и у меня бы вызов jndi прошёл.

А почему нельзя:
logger.debug($"Here goes my legitimate jndi call result: {externalParameterValue}");

где externalParameterValue = "jndi.Resolve(\"ldap:http://evil.addresss\"}" ?

(Подумав)С др. стороны, это все равно строка, т.е. externalParameterValue . Т.е. он просто напечатает
"jndi.Resolve("ldap:http://evil.addresss"}"

Но тогда в шарпе это надо было бы вызывать как-то явно и уже логгировать результат. Опять же, это была бы
изначально кривая функциональность. Тогда причем здесь интерполяция?

S>А вот такой вот код интерполяции jndi не вызовет:

S>
S>var externalParameterValue = "{jndi.Resolve(\"ldap:http://good.addresss\"}";
S>logger.debug($"Here goes my legitimate jndi call result:"+externalParameterValue);
S>


Тут по сути 2 строки складываются, и почему при этом должна быть одна из них интерполирована
Кодом людям нужно помогать!
Re[17]: Новогодний сюрприз от Apache
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.12.21 02:47
Оценка: 1 (1)
Здравствуйте, Sharov, Вы писали:


S>А почему нельзя:

S>
S>logger.debug($"Here goes my legitimate jndi call result: {externalParameterValue}");
S>

S>где externalParameterValue = "jndi.Resolve(\"ldap:http://evil.addresss\"}" ?
Можно. Но это просто подставит значение параметра, а не значение выражения в параметре.
S>(Подумав)С др. стороны, это все равно строка, т.е. externalParameterValue . Т.е. он просто напечатает
S>"jndi.Resolve("ldap:http://evil.addresss"}"
Это напечатает

Here goes my legitimate jndi call result: jndi.Resolve("ldap:http://evil.address")

S>Но тогда в шарпе это надо было бы вызывать как-то явно и уже логгировать результат. Опять же, это была бы
S>изначально кривая функциональность. Тогда причем здесь интерполяция?
При том, что интерполяция работает. Причём ожидаемым образом — в частности, выражение externalParameterValue не вычисляется, если отладочное логгирование отключено в конфигурации.

S>Тут по сути 2 строки складываются, и почему при этом должна быть одна из них интерполирована

Ну вот в log4j2 интерполируется результат сложения
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: fyi
От: Sharov Россия  
Дата: 23.12.21 00:43
Оценка:
Наконец-то и они отметились--
https://youtu.be/Opqgwn8TdlM
Кодом людям нужно помогать!
Re[18]: Новогодний сюрприз от Apache
От: Sharov Россия  
Дата: 23.12.21 12:37
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>Но тогда в шарпе это надо было бы вызывать как-то явно и уже логгировать результат. Опять же, это была бы

S>>изначально кривая функциональность. Тогда причем здесь интерполяция?
S>При том, что интерполяция работает. Причём ожидаемым образом — в частности, выражение externalParameterValue не вычисляется, если отладочное логгирование отключено в конфигурации.

Т.е. в яве она пытается зачем-то вычислить $"{some_expr}" при том, что some expr это просто строка? Если да, тогда
все ясно и это очень странно. В шарпе это тоже возможно, но явно $"{fn()}".
Вопрос -- а как они в яве тогда отличают обычные строки от необычных, анализируют что-то?
Как они понимают, что тут надо просто подставить значение, а тут надо jndi чего-то там?


S>>Тут по сути 2 строки складываются, и почему при этом должна быть одна из них интерполирована

S>Ну вот в log4j2 интерполируется результат сложения

Это как? Интерполяция -- это подстановка вычисления в строку. Оно может быть уже вычислено,
либо $"{fn()}".
Кодом людям нужно помогать!
Re[6]: Новогодний сюрприз от Apache
От: Sharov Россия  
Дата: 23.12.21 12:45
Оценка:
Здравствуйте, SkyDance, Вы писали:

vsb>>Вообще в жава с логгингом какое-то мракобесие.


SD>Мракобесие не в жаве с логгингом, а в самой идее решения проблемы рефакторинга путем добавления слоев.

SD>Потому как только самые продвинутые человеческие мозги могут решить проблему путем упрощения. Большинство будет надстраивать.

А почему это проблема, если упрощение можно достичь путем именно добавления слоев. Я вот ссылку выше привел,
где британские ученые именно этот подход и предлагают. Т.е. негоже такой функционал(jndi) в лог тащить.
Кодом людям нужно помогать!
Re[16]: Новогодний сюрприз от Apache
От: · Великобритания  
Дата: 23.12.21 13:38
Оценка: 3 (1)
Здравствуйте, Sinclair, Вы писали:

S>·>С другой стороны, смотрю я на реальный код и обычно вижу ("Fooing bar moo boo id={}, state={}", someStuff.getRequestId(), someStuff.getState())...

S>Ну, при должной обработке в логе так и будет someStuff.RequestId, someStuff.State.
У меня в уме какое-то разделение — логи должны быть для людей с ролью поддержки, т.е. их явно формируешь для читабельности. Экспозить имена локальных переменных, которые для читабельности кода, люди с ролью программиста — так себе... Другими словами, логи должны описывать что делается, а не как. Притом, когда я рефакторю код, обычно логгирование оставляю неизменным.
Впрочем не знаю, может это навязанная привычка, были бы другие фичи в библиотеке логгирования, привык бы к другому.

S>>>Всё же прочтите статью. После этого можно будет попробовать её разбрать на sharplab.io и посмотреть, что за код генерируется в итоге.

S>>>Разница между C# и интерполяцией из log2j2 не в поведении при отключении логгирования, а в безопасности.
S>·>Это криворукость конкретно log4j. В том же logback (альтернативная реализация того же slf4j api) такого идиотизма нет.
S>Эмм, а в чём конкретно криворукость? В самой идее интерполяции, или в её реализации?
S>Если второе, то как logback решает проблему безопасности?
В самой идее интерполяции, точнее в дизайне "фичи" сделать её рекурсивной. Сейчас поигрался, т.е. log.info("Hello {}", "abc${env:VALUE}efg"), где VALUE=123${env:VALUE2}456, VALUE2=XYZ будет раскрывать ${} до конца:
"Hello abc${env:VALUE}efg"
"Hello abc123${env:VALUE2}456efg"
"Hello abc123$XYZ456efg"

Т.е. как я понял, кому-то это показалось гениальной супер-полезной фичей... и никто не подумал, что это хрень какая-то, да ещё и дырища...
Если подумать... как вообще кому-то в голову такое могло прийти <10 лет назад??! И это в ИТ-индустрии наученной SQL-инъекциями...
Одно оправдывает. Этот подход часто используется в конфигурационных файлах и там оно действительно полезно. Но конфиги — таки доверяемый код. Короче, запилили фичу "как у всех" не подумав.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 23.12.2021 13:45 · . Предыдущая версия . Еще …
Отредактировано 23.12.2021 13:40 · . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.