duangsuse::Echo
412 subscribers
3.85K photos
105 videos
574 files
5.14K links
duangsuse技术相干订阅
这是 @duangsuse 与技术有关的发布频道
duangsuse 的另外有 throws 闲杂频道
@dsuset
转载频道 @dsusep
duangsuse 有coding,github,gitlab帐号和bilibili帐号

极小可能会有批评zf的消息 如有不适可以退出

suse的小站:https://piped.stream
ps 另有别名 popf.rip
ʕ•̀ω•́ʔ✧ 🐶🍎🏠生死🐜
(>ω<)岂因祸福避趋之 一鿕
Download Telegram
duangsuse::Echo
对于分支控制流分析来说,一个值得注意的点是『分支』的控制流是否有相同的后件: if (p) { console.log() } else { console.log() } 实际上可以被转化为 console.log() 这类情况可能很多,再比如一个差不多的 if (p) { stack.push(1); storage.set(1, stack.pop()); } else { stack.push(2); storage.set(1, stack.pop()); } 这…
有点问题, apache commons lang 的 random string 调用是 (IZZ)V
我以为 Z 是 Float 来着,然后 J 是 Boolean...
其实反过来了 #Java #reveng

然后调用 Java 的栈是后进先出的,所以第一个 bipush 上的是第一个参数...(然后 invokevirtual 是从最后一个参数开始 pop...)

好吧,我承认是我对栈的“可视化”弄错了,之前我这么想栈:

— 栈底
1
2
3
👆 栈顶

当然这是正确的(它的确是 LIFO),可是很多人不这么想,他们和我想的正好是反的

👇 栈顶
3
2
1
— 栈底

虽然,x86 的栈默认就是往低地址增长... 看起来这样会比较方便,可也有不方便的:
CDEF 和 Java 函数传参的时候看起来最先出栈的被视为最后一个参数,这很正常(这样调用时压入就不会那么鸡勒)
可是和我的直觉不怎么符合... 怎么看 invoke* 上面被 push 的(在模拟执行的时候)从下往上数和参数列表应该直接对应的,可是这么干给它反过来了,搞的即使有在模拟执行也不怎么好理解...

后面的是 boolean...

已经修改好了

String $_8 = org.apache.commons.lang3.RandomStringUtils.random(10,true,true);

rather than

String $_8 = org.apache.commons.lang3.RandomStringUtils.random(1,1,10);
反编译的程序拥有等价的逻辑语义
duangsuse::Echo
反编译的程序拥有等价的逻辑语义
但是我们依然可以使用 jad 来反编译它,即使我正打算自己写一个反编译器...

jar xf Yuuta\ \(2\).jar Base64AndDDoS.class
~/bin/jad158e.linux.static/jad Base64AndDDoS.class

Parsing Base64AndDDoS.class...The class file version is 52.0 (only 45.3, 46.0 and 47.0 are supported)
Generating Base64AndDDoS.jad

反编译的效果很好 🌚
区别是我完全没有看任何局部变量表,注意手动反编译的版本和机器自动反编译的版本都有一个循环,catch 块里他们都尝试 goto 到循环头部了

然后我反编译丢了 $const_flagbr 的读取,,,(其实是在后面的 catch landingpad 里读取的,但是我直接 continue; 了没判断 iload_1; ifeq 276 @276: aload 12; athrow) 🙈
javap -l Base64AndDDoS 可以输出行号和本地变量表
我总算不怕面向对象设计了, JavaEE 果然是大佬的平台, 什么 Representation, Resource links(rel/href/type, LinkableRepresentation), Adapter, 方法限定子类, Utils, 函数指针式子类实现已经是小 case 了
都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current, @Startup Bean, Interceptor, Stereotype, CDI Observer, NDI, DevOps, ShrinkWrap 部署 Archive 文件系统 DSL, 灰盒测试, XML 配置, Graph databases, 数据网格, JPA/JTA, BeanManager 了

到处隐式对象依赖 @Observes @interface @XXXScoped @Produces @Starup @PostConstruct @Resource 到处组件化、元编程、事务性、测试、abstract class 和 type parameters 看起来才像是 JavaEE 啊
duangsuse::Echo
我总算不怕面向对象设计了, JavaEE 果然是大佬的平台, 什么 Representation, Resource links(rel/href/type, LinkableRepresentation), Adapter, 方法限定子类, Utils, 函数指针式子类实现已经是小 case 了 都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current, @Startup Bean, Interceptor,…
亏它还说是『接地气』的指南,果然只是指南而已,这根本不是 Java 入门级别开发者能 handle 的复杂度啊!

就是那个 SMTPMailService (还是封装了 JavaEE 本身的 javax.mail API)恐怕初学者不写个一两天也是弄不出来的(涉及上下文依赖注入、JNDI 服务查找、javax.mail.* API、JMX Queue、MessageDriven Bean、XML、java.util.concurrent.CyclicBarrier 同步工具类、Subetha SMTP Server、测试部署过程、...)

然鹅,对很多人来说,他们对『“服务端”发送一封邮件』的直觉是:

abstract fun sendMail(toAddr: String, subject: String, body: String)

或者

abstract fun sendMail(toAddr: String, subject: String, body: String, mime: MimeType)

或者

abstract fun sendMail(toAddr: String, subject: String, body: String, mime: MimeType): Future<MailSendResult>

...

可是你却要教他们用 java.io.Serializable 去用 Builder pattern 去生成什么“可变”“不可变” “线程安全传输” 的 MailMessage 对象

@Inject MailService mailer;

//...
MailMessage smg = new MailMessage.Builder()
.from("duangsuse@example.org")
.addTo("cxk@example.org")
.subject("Re: 🏀 挑战")
.body("😧").type(MimeType.TEXT_PLAIN)
.build();

mailer.queueForDelivery(smg);

而且后面还有一大堆被模块化松耦合的逻辑... 寻找 javax.mail.Session 资源啊、拿到注入 smtpQueue 啊、拿到 Java JMX 的 ConnectionFactory 啊、发送到消息队列啊(之间又要用到数个 API,比如 ObjectMessage、Session、(Message)Producer,到了队列的 MessageDriven Bean 里又要 Check cast 两次确保运行时类型安全,而且这还需要一个 sendMail(final MailMessage) 的辅助,这个函数的逻辑还仅仅只是把 MailMessage 翻译成 MimeMessage 然后 Transport.send 而且它也是一个 Bean @EJB... 还有 MessageDriven Bean 还要填写个 annoatation 元数据、这个 annotation 里面还需要仨 annotation(acknowledgeMode, destination, destinationType) 才能工作(Java Connector Architect),这仨还是 Java 经典令人头疼的 property(Map<String,Object>) 模式)...

Java 面向对象本来是为了降低门槛,可是 JavaEE 却是在背道而驰,因为它要通过提升编程难度、记忆模式数量的方式使得软件更容易维护更新测试.... 这样看起来才像是“企业级”软件
duangsuse::Echo
我总算不怕面向对象设计了, JavaEE 果然是大佬的平台, 什么 Representation, Resource links(rel/href/type, LinkableRepresentation), Adapter, 方法限定子类, Utils, 函数指针式子类实现已经是小 case 了 都在玩 CDI, Singleton Bean, Stateless Bean, SessionScoped/RequestScoped/Current, @Startup Bean, Interceptor,…
#JavaEE #Java #web #backend #statement #dev

在我们完全无视软件需求的情况下,Java EE 看起来就像是无端制造复杂度[1],从这一点上看起来,我觉得《Python 机器学习快速入门》这本书的作者对 OO 的观点是有点道理的。

(大意)

有人说“面向对象”最大的好处就是方便把人脑子搅乱。

Linux, Windows, UNIX, Mac OSX 的内核都是 C 语言、汇编写的,可唯独有一个操作系统不一样,就是 Nokia 的塞班系统,是用面向对象编程语言 C++ 写的内核,据说这个内核的代码量比 Windows XP 还大,连他们自己的程序员都维护不了,最后当然就死掉了。

简而言之,面向对象的代码风格:一个字『繁』、两个字『繁繁』、三个字『繁繁繁』

把 Python 视为非“面向对象”编程语言并非大逆不道,事实上,也有许多人认为 Python 是一种类似 LISP 的“函数”编程语言

笔者从事编程十余年
(敲黑板!)
,从未用过面向对象的编程模式写一行“class”(类对象)代码,依然可以应对各种编程工作

“面向对象”的鼻祖 C++11 标准,到 2015 年依然处于推广阶段,而且争议纷纷。

“面向对象”过于复杂,与“人生苦短,我用 Python”的优雅风格天生不合

可是我也这么想:虽然有时候我们希望 Quick hack,做我们想做的事情,写点小东西自娱自乐(有时候不一定非常辣鸡,也可能只是比较精巧而已)或者写点『复杂的堆砌』(就是规模大一点的小程序)出来,
但是,实际上世界是极其丰富多彩(̶e̶g̶.̶ ̶与̶你̶无̶瓜̶、̶蓝̶瘦̶香̶菇̶、̶鸡̶你̶太̶美̶、̶图̶样̶图̶森̶破̶)̶的,有自己 自娱自乐♂ 的需求也自然有 搞♂大新闻 的需求

Intermediate Representation : Literate Agda => 形式验证、依赖类型与动态类型 [博文]

程序员们常常对『动态类型和静态类型哪个更好』这一话题产生激烈的讨论。 这其实是一个完全没有意义的讨论,因为这首先是一个罗卜白菜的问题——两者都有能称得上是『优点』的地方;
其次不同的人对程序有不同的追求,有人想写出健壮可扩展的程序,有人只是想快速交付收钱; 再其次同一个人也有不同的需求,有时只是想批量处理一些文件,有时需要构建长期维护的大型项目。

同样,Continuous EnterpriseDevelopment in Java [GitHub] 这本书的作者也说:

If you are only interested in quick hacks, you will hate Java EE, applications servers andprobably this book alltogether.

Packaging, deployment, monitoring and management sounds like bloat and is bloat, if you are only focusing on development.

However the “DevOps” movement also considers operations and development as asingle unit. Who needs beautiful code which cannot be properly installed in a predefinedenvironment? DevOps is nothing groundbreaking; rather it’s a “back to the roots”movement.

是这样就证明“面向对象编程万恶复杂”是错误的观点?不,但是我觉得,对任何事物都不要盲目武断其性质,对任何领域的任何事情也都应该以这种原则判断

duangsuse 曾经在冰封哥 @ice1000 和 friends 当管理的某 Q群里发了诸如“我觉得 Haskell 的 HM 类型系统很垃圾,无端制造复杂性”[2]这种弱智级的言论(黑历史啊,我都是抖着手打出来的,后面半句是大致的意思)

为什么觉得奇怪、莫名其妙?很大的情况下可能是因为自己根本不理解,正如我开始写一点 Haskell 以后对我上面这种话的评论:

听不到音乐的人觉得跳舞的人都疯了!

参见 Dunning-Kruger 效应,为什么刚入门的小白居然有那个胆量去挑战他们所谓的“权威”?为什么一个普通院校的高中生居然敢以不到一页 A4 纸的篇幅证明几百年(敲黑板)来没人破解的哥巴赫猜想?因为他们真的已经弱到连自己的弱、别人的 dalao 都感受不到了。

所以有时候,看到『存在即合理』这句话,不要忘记它还有一个深层含义:
如果你一看到某件东西就觉得它很莫名其妙,很弱智,那就不要立刻去喷它,因为
存在即合理

如果你依然坚持自己的看法,为什么不思考一下,每天有无数人和你持一样的想法,为什么没有人做出点什么证明它真的没有道理?
是因为它后台很硬,还是看不到它合理性的你们 — 都太菜了?


[1]: 制造的复杂度大部分就是少量模板的代码,以及对某些逻辑做对象化抽象后过度的拆分,比如 @ApplicationScoped @Singleton @LocalBean @TransationAttribute(...) public class XXX {...} 这种,以及把消息队列的使用给拆成『连接器、会话、生产者』和『消息队列』两部分这种情况
我觉得这句话和“在我们完全无视 Haskell 是一门引用透明且惰性求值语言的情况下,Monadic IO 看起来就像是无端制造复杂度”听起来怎么就那么像🌚
[2]: 我当时真的不止是没有写过一行 Haskell,我是压根一行 Haskell 代码都没有看过。
HM 这个名词是我从王某人的博客上看到的
duangsuse::Echo
#JavaEE #Java #web #backend #statement #dev 在我们完全无视软件需求的情况下,Java EE 看起来就像是无端制造复杂度[1],从这一点上看起来,我觉得《Python 机器学习快速入门》这本书的作者对 OO 的观点是有点道理的。 (大意) 有人说“面向对象”最大的好处就是方便把人脑子搅乱。 Linux, Windows, UNIX, Mac OSX 的内核都是 C 语言、汇编写的,可唯独有一个操作系统不一样,就是 Nokia 的塞班系统,是用面向对象编程语言…
#blog #recommended http://www.yinwang.org/blog-cn/2019/01/30/machine-learning

弄了半天我才知道啥叫逻辑式(descriptive)编程... 虽然之前某学姐的语录给了我帮助(神经网络是有未知参数的程序!)

miniKaren 里:

(run*(x)
(exists (x)
(== (+ x 2) 5))) ; 偷了点懒,我直接用了示例程序

当然我不可能懒到只给示例程序

(∃x∈ℚ. x + 2 = 5) ⇒ x

其中:
⇒ 不是逻辑里蕴含的意思,而是『给定某些条件,推出某式子的值』的意思 (run*)
∃x∈ℚ. x + 2 = 5 是一个命题,也就是条件

但是我之前知道所谓的『测试驱动编程』(Test-Driven programming)
但是我之前只是知道 Prolog, Coq 是 “逻辑式编程语言” 而已,我不知道所谓“逻辑式”是要以“某种给定条件成立”为编程的方法,甚至把 Agda 当成了逻辑式(有点像了,但还不是)

当然,Agda 是一个 Proof Assistent,不过看起来,如果 Agda 也能像 Z3 一样全自动完成定理证明那也是“逻辑式”语言了
This media is not supported in your browser
VIEW IN TELEGRAM
我还是继续写我的 Jawa you dont know
_emscripten_asm_const_i
_emscripten_asm_const_ii

两条 WASM 支持 library function 实现的问题,导致使用

var ASM_CONSTS = [
(function () {
var err = new Error;
print('Stacktrace: \n');
print(err.stack)
})
, ...];

年度最佳 👍+1
只要是生成代码里有 code=0 的情况,就会 print 🌚

1/(0-1+Int32.Parse("1")); 这种表达式不会有问题
Math.Round(0.1, MidpointRounding.AwayFromZero); 就会有问题

然后你看看(M$ 服务器编译后在你的浏览器上 WASM 运行时运行的)
有问题的函数打上断点

JSON 解析两次请求执行的函数,可以拿到一个请求结果代码对象

(当然也可以直接 POST compile?hostOrigin=... 拿目标 IL ,可在 HTTP 请求处查询)
DLL IL 反汇编后是这样:

dotnet tool install -g dotnet-ildasm

.method public hidebysig static void Main() cil managed
ldc.r8 0.1
ldc.i4.1
call double [netstandard]System.Math::Round(double, [netstandard]System.MidpointRounding)
pop
ret

可是
var _mono_wasm_invoke_method = Module['_mono_wasm_invoke_method'] = (function () {
return Module['asm']['_mono_wasm_invoke_method'].apply(null, arguments)
});

然后我们就啥都不知道了...(这是 Instrinic 函数,而且很明显,它的定义压根就是递归的,运行时没人 trap 它根本它就会一直等着直到栈溢出)

https://github.com/WebAssembly/design/issues/769

emscripten_asm_const_[signature]

EM_ASM_INT
 (emscripten_asm_const_int)
这才知道这是某个 Round(AwayFromZero) 实现往啥地方放了 constant int?

https://github.com/mono/mono/blob/master/netcore/System.Private.CoreLib/shared/System/Math.cs#L802
https://github.com/mono/mono/blob/affb833a6d87ce00b6084fd81f1a9a6fd3abd8f0/netcore/System.Private.CoreLib/shared/System/MathF.cs

但是很麻烦啊,不过还好,我的 Firefox 最终成功启用了 WASM 调试,可以动态阅读 WASM 反汇编
(import "env" "_emscripten_asm_const_i" (func $import24 (param i32) (result i32)))

...
(func $func5951 (param $var0 i32) (param $var1 i32) (param $var2 i32) (param $var3 i32) (param $var4 i32)
...
if
i32.const 0
call $import24
drop

问题就在这里!它调用了有问题的 _emscripten_asm_const_i, 这个函数的行为只有在为 1 时才正常(EM_ASM 的正常功能 eval 代码)

这个函数本身是 『调用一个没有参数的函数指针』

运行时它被 ASM_CONSTS 实现, code 代表什么鬼

可是这个函数叫什么名字呢

机制地根据 Math.cs 的魔数找到了一点对应的逻辑

找到一个!

MathTest.cs#L179 对应 mono.wasm@C8E6B
Firefox (划重点)完全支持 WebAssembly 调试(除了不能随意跳转而已...)
This media is not supported in your browser
VIEW IN TELEGRAM
我终于觉悟了!原来我看了半天常量,其实我在调试的部分根本不在 System.Math 类里!
它是一个已经准备好进行终止的程序!