Michael.W基于Foundry精读Openzeppelin第1期——Address.sol

news2024/9/25 23:25:47

Michael.W基于Foundry精读Openzeppelin第1期——Address.sol

      • 0. 版本
        • 0.1 Address.sol
      • 1. 目标合约
      • 2. 代码精读
        • 2.1 isContract(address)
        • 2.2 sendValue(address, uint256)
        • 2.3 functionCall(address, bytes memory) && functionCall( address, bytes memory, string memory)
        • 2.4 functionCallWithValue(address, bytes memory, uint256) && functionCallWithValue(address, bytes memory, uint256, string memory)
        • 2.5 functionStaticCall(address, bytes memory) && functionStaticCall(address, bytes memory, string memory)
        • 2.6 functionDelegateCall(address, bytes memory) && functionDelegateCall(address, bytes memory, string memory)

0. 版本

[openzeppelin]: v4.8.3,[forge-std]: v1.5.6

0.1 Address.sol

Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/utils/Address.sol

1. 目标合约

封装Address library成为一个可调用合约:
Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/src/utils/MockAddress.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/utils/Address.sol";

contract MockAddress {
    using Address for address;
    using Address for address payable;

    uint public slot0;
    address public slot1;

    function isContract(address target) external view returns (bool){
        return target.isContract();
    }

    function sendValue(address payable recipient, uint amount) external {
        recipient.sendValue(amount);
    }

    function functionCall(address target, bytes memory data) external returns (bytes memory){
        return target.functionCall(data);
    }

    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) external returns (bytes memory) {
        return target.functionCall(data, errorMessage);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint value
    ) external returns (bytes memory){
        return target.functionCallWithValue(data, value);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint value,
        string memory errorMessage
    ) external returns (bytes memory){
        return target.functionCallWithValue(data, value, errorMessage);
    }

    function functionStaticCall(address target, bytes memory data) external view returns (bytes memory){
        return target.functionStaticCall(data);
    }

    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) external view returns (bytes memory) {
        return target.functionStaticCall(data, errorMessage);
    }

    function functionDelegateCall(address target, bytes memory data) external returns (bytes memory) {
        return target.functionDelegateCall(data);
    }

    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) external returns (bytes memory){
        return target.functionDelegateCall(data, errorMessage);
    }
}

全部foundry测试合约:

Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/test/utils/Address.t.sol

2. 代码精读

2.1 isContract(address)

该方法是通过查看一个地址下code的长度来判断该地址是否是合约地址。如果传入地址为合约地址,返回true。

注意:但是有个特例:由于一个合约地址的code会在该合约的constructor函数执行完才被存储,所以如果另外一个合约在它的constructor函数中对该函数进行调用,那么返回值将是false。

代码解读

function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
}

如果单纯通过该方法的返回值来判断一个地址是否为合约地址其实是不安全的。以下情况该方法都会返回false:

  • EOA地址;
  • 一个处于constructor函数中的合约地址;
  • 即将在该地址上创建合约的地址(例如:利用salt提前计算出的地址);
  • 一个被destroy的合约地址。

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();
    SelfDestructorCase sdc;

    function setUp() external {
        // 由于一个合约的销毁会在一笔tx的执行结束时执行,所以将selfdestruct()的调用放在setUp()中
        // 这样在每个test用例中sdc合约已经是被selfdestruct了
        sdc = new SelfDestructorCase();
        // destruct the contract
        sdc.kill();
    }

    function test_IsContract() external {
        // contract address
        assertTrue(testing.isContract(address(this)));
        // eoa address
        assertFalse(testing.isContract(msg.sender));
    }

    function test_IsContract_SpecialCase_Constructor() external {
        // case 1: 处于constructor时期的合约地址,isContract()会返回false
        ConstructorCase cc = new ConstructorCase(testing);
        assertFalse(cc.flag());
    }

    function test_IsContract_SpecialCase_ContractDestroyed() external {
        // case 2: 销毁后的合约地址,无法被识别出来
        assertFalse(testing.isContract(address(sdc)));
    }
}

contract ConstructorCase {
    bool public flag;
    constructor(MockAddress ma){
        flag = ma.isContract(address(this));
    }
}

contract SelfDestructorCase {
    function kill() external {
        selfdestruct(payable(msg.sender));
    }
}

所以并不能通过isContract方法来地址闪电贷攻击!而且在合约开发中是不提倡禁止合约的调用,因为这样会使得很多合约钱包失效(比如Gnosis Safe)。

2.2 sendValue(address, uint256)

转账eth。

代码解读

function sendValue(address payable recipient, uint256 amount) internal {
    	// 判断本合ETH余额是否满足转账需求
        require(address(this).balance >= amount, "Address: insufficient balance");
		// 通过.call()转账
        (bool success, ) = recipient.call{value: amount}("");
      	// 如果转账失败,回滚交易
        require(success, "Address: unable to send value, recipient may have reverted");
}

注:普通的.transfer()转账有2300 gas的限制,而该方法则取消该限制。但是使用该方法时需要注意防止重入。

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();

    function test_SendValue() external {
        Receiver r = new Receiver();
        address payable recipient = payable(address(r));
        assertEq(recipient.balance, 0);
        vm.deal(address(testing), 1 ether);

        testing.sendValue(recipient, 1 ether);

        assertEq(recipient.balance, 1 ether);
        assertEq(address(testing).balance, 0);

        // revert check
        vm.deal(address(testing), 1 ether);
        // case 1: insufficient balance
        vm.expectRevert("Address: insufficient balance");
        testing.sendValue(recipient, 2 ether);

        // case 2: send eth to the contract with no revert in receive function
        r.setEthReceived(false);
        vm.expectRevert("Address: unable to send value, recipient may have reverted");
        testing.sendValue(payable(address(r)), 1 ether);
    }
}

contract Receiver {
    bool _ethReceived = true;

    function setEthReceived(bool ethReceived) external {
        _ethReceived = ethReceived;
    }

    receive() external payable {
        if (!_ethReceived) {
            revert("revert in receive function");
        }
    }
}

2.3 functionCall(address, bytes memory) && functionCall( address, bytes memory, string memory)

functionCall(address, bytes memory) :不带value值,传入目标合约地址和对应的payload进行底层的call调用。如果call调用的方法中产生revert,本函数将解析出该revert的信息并在本层以相同的内容引发revert(正常solidity的external调用就是这样的行为)。

要求:target地址必须为合约地址。

functionCall( address, bytes memory, string memory):如果call调用的方法产生的revert不带msg,那么在本层指定msg抛出revert。

代码解读

function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        // 设置value为0,进行底层的call调用。如果call失败且无返回值,那么将引起"Address: low-level call failed"的revert
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
} 

// 如果call调用的方法产生的revert不带msg,那么在本层指定msg抛出revert。
function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
    		// 指定revert msg
        return functionCallWithValue(target, data, 0, errorMessage);
}

// 携带value进行call调用
function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
    		// 检查余额是否满足转账
        require(address(this).balance >= value, "Address: insufficient balance for call");
        // 携带calldata进行底层call
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        // 检查call的成功与否与返回值。如果是在call的函数中发生revert,会在本层获取该revert信息并引发revert(正常solidity的external调用就是这样)
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
 }
 
// 验证call的结果和返回值
// - 如果call成功:
//      - 如果有返回值,返回返回值;
//      - 如果无返回值,要求target必须是合约地址;
// - 如果call失败:
//      - 如果有返回值(返回值为call的方法中revert出的信息),从该返回值中获取revert的信息
//      - 如果无返回值,利用指定的errorMessage触发新的revert
function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
    		// 如果call的返回是成功
        if (success) {
        		// 如果call调用的函数没有返回值
            if (returndata.length == 0) {
                // 检查call的对象必须是一个合约
                require(isContract(target), "Address: call to non-contract");
            }
            // 返回call的具体的返回值
            return returndata;
        } else {
        		// 如果call返回的是失败
            _revert(returndata, errorMessage);
        }
}

// 在call失败的情况下,从returndata中获取call的方法中引起的revert的信息。如果没有该信息,则引发一个errorMessage的revert
function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // (在call失败的情况下)如果call的有返回值,说明call调用的方法中发生revert,revert的具体字符串描述被返回过来
        if (returndata.length > 0) {
            // 使用汇编来获取returndata中包裹的revert信息
            assembly {
            		// returndata_size为returndata的数据长度,即returndata指针开始到其后32字节之间存储的指
                let returndata_size := mload(returndata)
                // 发生revert,revert的内容:从returndata指针后32字节作为起始位置,内容长度为returndata_size
                revert(add(32, returndata), returndata_size)
            }
        } else {
        		// 如果没有返回值,说明call方法中并没有revert具体的信息返回,直接用errorMessage引起revert
            revert(errorMessage);
        }
}

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();

    function test_FunctionCall() external {
        Target t = new Target();
        bytes memory returndata = testing.functionCall(
            address(t),
            abi.encodeCall(t.setSlot0, (1024))
        );

        assertEq(t.slot0(), 1024);
        assertEq(abi.decode(returndata, (uint)), 1024 + 1);

        // check revert
        // case 1: revert if target is eoa
        vm.expectRevert("Address: call to non-contract");
        testing.functionCall(msg.sender, "");

        // case 2: revert with the bubbled revert msg
        vm.expectRevert("revert with msg");
        testing.functionCall(
            address(t),
            abi.encodeCall(t.revertWithMsg, ())
        );

        // case 3: revert with specific msg if the target function reverts with no msg
        vm.expectRevert("Address: low-level call failed");
        testing.functionCall(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ())
        );

        vm.expectRevert("specific revert msg");
        testing.functionCall(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ()),
            "specific revert msg"
        );
    }
}

contract Target {
    uint public slot0;

    function setSlot0(uint n) external returns (uint){
        slot0 = n;
        return n + 1;
    }

    function revertWithMsg() external payable {
        revert("revert with msg");
    }

    function revertWithNoMsg() external payable {
        revert();
    }

    function payableFunc() external payable returns (uint){
        return msg.value;
    }
}

2.4 functionCallWithValue(address, bytes memory, uint256) && functionCallWithValue(address, bytes memory, uint256, string memory)

functionCallWithValue(address, bytes memory, uint256)和functionCallWithValue(address, bytes memory, uint256, string memory) 就是带value的call调用,其他逻辑处理与functionCall(address, bytes memory)一致。只是functionCallWithValue(address, bytes memory, uint256, string memory)可以在call的目标函数发生revert无msg时指定本层的revert信息。

要求:target地址必须为合约地址。

代码解读(见1.3的代码解读)

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();

    function test_FunctionCallWithValue() external {
        Target t = new Target();
        vm.deal(address(testing), 1 ether);
        bytes memory returndata = testing.functionCallWithValue(
            address(t),
            abi.encodeCall(t.payableFunc, ()),
            1 ether
        );

        assertEq(abi.decode(returndata, (uint)), 1 ether);
        assertEq(address(t).balance, 1 ether);

        // check revert
        vm.deal(address(testing), 1 ether);
        // case 1: revert if target is eoa
        vm.expectRevert("Address: call to non-contract");
        testing.functionCallWithValue(msg.sender, "", 1 ether);

        // case 2: revert if insufficient balance
        vm.expectRevert("Address: insufficient balance for call");
        testing.functionCallWithValue(
            address(t),
            abi.encodeCall(t.payableFunc, ()),
            2 ether
        );

        // case 3: revert with the bubbled revert msg
        vm.expectRevert("revert with msg");
        testing.functionCallWithValue(
            address(t),
            abi.encodeCall(t.revertWithMsg, ()),
            1 ether
        );

        // case 4: revert with specific msg if the target function reverts with no msg
        vm.expectRevert("Address: low-level call with value failed");
        testing.functionCallWithValue(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ()),
            1 ether
        );

        vm.expectRevert("specific revert msg");
        testing.functionCallWithValue(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ()),
            1 ether,
            "specific revert msg"
        );
    }
}

contract Target {
    uint public slot0;

    function setSlot0(uint n) external returns (uint){
        slot0 = n;
        return n + 1;
    }

    function revertWithMsg() external payable {
        revert("revert with msg");
    }

    function revertWithNoMsg() external payable {
        revert();
    }

    function payableFunc() external payable returns (uint){
        return msg.value;
    }
}

2.5 functionStaticCall(address, bytes memory) && functionStaticCall(address, bytes memory, string memory)

向目标地址发起static call(不能在staticcall中修改状态变量,否则会revert)。其他逻辑处理与functionCall(address, bytes memory)一致。

要求:target地址必须为合约地址。

代码解读

// 向目标地址发起static call
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
 }

// 如果本static call的目标方法中产生revert无msg,则在本层发起指定msg为errorMessage的revert
function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
    		// 底层通过static call来实现合约间的调用
        (bool success, bytes memory returndata) = target.staticcall(data);
        // 检查static call的成功与否与返回值。如果是在static call的函数中发生revert,会在本层获取该revert信息并引发revert(正常solidity的external调用就是这样)
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
 }

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();

    function test_functionStaticCall() external {
        Target t = new Target();
        bytes memory returndata = testing.functionStaticCall(
            address(t),
            abi.encodeCall(t.slot0, ())
        );

        assertEq(abi.decode(returndata, (uint)), 1);

        // check revert
        // case 1: revert if target is eoa
        vm.expectRevert("Address: call to non-contract");
        testing.functionStaticCall(msg.sender, "");

        // case 2: revert with the bubbled revert msg
        vm.expectRevert("revert with msg");
        testing.functionStaticCall(
            address(t),
            abi.encodeCall(t.revertWithMsg, ())
        );

        // case 3: revert with specific msg if the target function reverts with no msg
        vm.expectRevert("Address: low-level static call failed");
        testing.functionStaticCall(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ())
        );

        // revert if the target function tries to modify the storage
        vm.expectRevert("specific revert msg");
        testing.functionStaticCall(
            address(t),
            abi.encodeCall(t.setSlot0, (1024)),
            "specific revert msg"
        );
    }
}

contract Target {
    uint public slot0 = 1;

    function setSlot0(uint n) external returns (uint){
        slot0 = n;
        return n + 1;
    }

    function revertWithMsg() external payable {
        revert("revert with msg");
    }

    function revertWithNoMsg() external payable {
        revert();
    }

    function payableFunc() external payable returns (uint){
        return msg.value;
    }
}

2.6 functionDelegateCall(address, bytes memory) && functionDelegateCall(address, bytes memory, string memory)

向目标地址发起delegate call(使用调用者的上下文)。其他逻辑处理与functionCall(address, bytes memory)一致。

要求:target地址必须为合约地址。

代码解读

// 向目标地址发起delegate call
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}

// 如果本delegate call的目标方法中产生revert无msg,则在本层发起指定msg为errorMessage的revert
function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
    		// 底层通过delegate call来实现合约间的调用
        (bool success, bytes memory returndata) = target.delegatecall(data);
        // 检查delegate call的成功与否与返回值。如果是在delegate call的函数中发生revert,会在本层获取该revert信息并引发revert(正常solidity的external调用就是这样)
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}

foundry代码验证

contract AddressTest is Test {
    MockAddress testing = new MockAddress();

    function test_functionDelegateCall() external {
        Target t = new Target();
        bytes memory returndata = testing.functionDelegateCall(
            address(t),
            abi.encodeCall(t.setSlot0AndReturnSlot1, (1024))
        );

        // return the value of slot 1 in contract MockAddress
        assertEq(abi.decode(returndata, (address)), address(0));
        // delegate call set slot 1 value in contract MockAddress
        assertEq(testing.slot0(), 1024);
        // slot 1 value in target contract not set
        assertEq(t.slot0(), 1);

        // check revert
        // case 1: revert if target is eoa
        vm.expectRevert("Address: call to non-contract");
        testing.functionDelegateCall(msg.sender, "");

        // case 2: revert with the bubbled revert msg
        vm.expectRevert("revert with msg");
        testing.functionDelegateCall(
            address(t),
            abi.encodeCall(t.revertWithMsg, ())
        );

        // case 3: revert with specific msg if the target function reverts with no msg
        vm.expectRevert("Address: low-level delegate call failed");
        testing.functionDelegateCall(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ())
        );

        vm.expectRevert("specific revert msg");
        testing.functionDelegateCall(
            address(t),
            abi.encodeCall(t.revertWithNoMsg, ()),
            "specific revert msg"
        );
    }
}

contract Target {
    uint public slot0 = 1;
    address public slot1 = address(1);

    function setSlot0(uint n) external returns (uint){
        slot0 = n;
        return n + 1;
    }

    function revertWithMsg() external payable {
        revert("revert with msg");
    }

    function revertWithNoMsg() external payable {
        revert();
    }

    function payableFunc() external payable returns (uint){
        return msg.value;
    }

    function setSlot0AndReturnSlot1(uint n) external returns (address){
        slot0 = n;
        return slot1;
    }
}

ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
如果需要转发,麻烦注明作者。十分感谢!
在这里插入图片描述

公众号名称:后现代泼痞浪漫主义奠基人

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/712656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaSE基础(上)

目录 第一章 java入门 环境配置 常用cmd命令 打开cmd 安装JDK:Java工具包 IDEA 1 IDEA概述(1)IDEA概述:IDEA全称IntelliJ IDEA,是用于Java语言开发的集成环境,是业界公认的目前用于Java程序开发最…

ABeam News | 乘云而上,扬帆起航——ABeam Consulting 2023 RISE+BTP私享会圆满落幕

当今中国,数字经济大潮风起云涌,数字化转型已经成为企业发展的“必修课”。对于企业来说,如何在数字化浪潮中奋楫扬帆,借助技术和管理手段助力企业“提质、降本、增效”,成为发展中所亟待解决的问题。 6月1日&#xf…

LED显示屏四大连接方式

LED显示屏的四大连接方式是数据连接、电源连接、信号输入连接和控制系统连接。以下是对每种连接方式的详细说明: 1,数据连接: 数据连接用于传输显示内容的数据信号到LED显示屏。常见的数据连接方式包括: 串行连接(Serial Connecti…

离开Kubernetes也能玩转Dapr

Dapr 被设计成一个面向开发者的企业级微服务编程平台,它独立于具体的技术平台,可以运行在“任何地方”。Dapr本身并不提供“基础设施(infrastructure)”,而是利用自身的扩展来适配具体的部署环境。就目前的状态来说&am…

nacos身份认证绕过漏洞

1.影响范围 Nacos < 2.0.0-ALPHA.1 2.验证漏洞是否存在 http://example/nacos/v1/auth/users/?pageNo1&pageSize5 如果列出了用户名密码,即证明此漏洞存在 3.向系统中添加一个新的用户 http://example/nacos/v1/auth/users/?usernamesectest&passwordsectest…

目录爆破工具(dirb、dirsearch)

一、dirb概述。 dirb是一个基于字典的web目录扫描工具&#xff0c;采用递归的方式来获取更多的目录&#xff0c;可以查找到已知的和隐藏的目录&#xff0c;它还支持代理和http认证限制访问的网站。 二、dirb常用参数。 三、基础操作。 1.直接扫描 dirb http://192.168.84.1…

Python财经股票数据获取, 保存表格文件

目录标题 前言环境使用:模块使用]:代码展示尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 环境使用: Python 3.8 解释器 Pycharm 编辑器 模块使用]: import requests —> 数据请求模块 pip install requests import csv 第三方模块安装: win R 输入cmd 输…

SpringBoot 3.1 新版HTTP调用

在SpringBoot3版本发布后 官方便声明了推荐使用了内置声明式的HTTP客户端。 一、声明式HTTP客户端使用(依赖引入) <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></depende…

Dhrystone基准测试程序在Google Pixel4上运行跑分教程

记录一下实验过程&#xff0c;方便后续回顾 一、Dhrystone简介 Dhrystone是测量处理器运算能力的最常见基准程序之一&#xff0c;常用于处理器的整型运算性能的测量。程序是用C语言编写的&#xff0c;因此C编译器的编译效率对测试结果也有很大影响。 但其也有许多不足&#x…

常见人脸检测器, 调用摄像头检测人脸

常见人脸检测器, 调用摄像头检测人脸 文章目录 常见人脸检测器, 调用摄像头检测人脸[TOC](文章目录) 前言一、导入相关包二、Haar检测器三、Hog检测器四、CNN检测器五、SSD检测器六、MTCNN检测器七、Opencv结合检测器检测人脸7.1 Hog 检测器7.2 Haar检测器 前言 主要介绍几种常…

【花雕】全国青少年机器人技术一级考试模拟题(之一)

一.单选题&#xff08;20题&#xff0c;每题3分&#xff09; 1.下列图片中&#xff0c;哪个不是机器人&#xff08;&#xff09; 答案&#xff1a;D 2.机器人的英文单词是&#xff08;&#xff09; A. botre B. boret C. robot D. rebot 答案&#xff1a;C 3.机器人结构中&am…

网络安全进阶学习第六课——服务器解析漏洞

文章目录 1、概念2、Apache解析漏洞 CVE-2017-157153、Apache AddHandler解析漏洞4、IIS6 解析漏洞&#xff08;;&#xff09;5、IIS6 解析漏洞&#xff08;*.asp/目录&#xff09;6、IIS7 解析漏洞&#xff08;ISAP或CGI的模式下&#xff09;7、nginx解析漏洞&#xff08;cgi.…

USB 3.0 Rx Detect之超速U盘的识别

1 USB超速SerDes原理介绍 1.1 SerDes Rx.Detect SerDes Rx.Detect的原理比较简单&#xff0c;就是通过一个逻辑电路比较RC时间常数的大小。 - 当Rx不存在时&#xff0c;RC时间常数较小。 - 当Rx存在时&#xff0c;RC时间常数较大。 下面将详细描述其原理。 Figure 1-1 USB 3.0电…

SuperMap 的 Environment.initialization(this)空指针

如果你把ndk和动态权限等等都设置好了&#xff0c;还发现Environment.initialization(this)还有空指针问题存在。就试试我这个方法 许可文件要用10i的&#xff0c;别用11i的 SuperMap 有个so库文件是放在armeabi-v7a文件夹下的&#xff0c;armeabi-v7a不要放在jniLibs目录下&…

深度理解:Redis Hash(散列表)实现原理

Redis是一种开源的&#xff0c;基于内存的数据结构存储系统&#xff0c;可以用作数据库、缓存和消息代理。它支持多种类型的数据结构&#xff0c;例如字符串、散列表、列表、集合、有序集合等。今天我们将重点讨论Redis的一个重要数据结构&#xff1a;Hash&#xff0c;也叫散列…

Linux网络概念

1.1网络 是由若干结点和连接这些结点的链路组成&#xff0c;网络中的结点可以是计算机&#xff0c;交换机、路由器等设备 网络设备有&#xff1a;交换机、路由器、集线器 传输介质有&#xff1a;双绞线、同轴电缆、光纤 1.2互联网 把多个网络连接起来就构成了互联网&#…

vue+antd——实现拖拽上传文件——技能提升

最近看到有2023年博客之星的入围状况&#xff0c;提示我还差24篇高质量文章才可以入围。前两年由于比较勤奋&#xff0c;文章篇数足够&#xff0c;因此没有遇到这种提示过。现在补上几篇文章&#xff0c;希望可以入围吧。 1.html代码 <template><div class"clea…

编译linux内核(三)

内核配置选项[Centos] 挑选核心功能选项介绍1. General setup&#xff08;通用选项&#xff09;2. Enable loadable module support3. Enable the block layer4. Processor type and features(CPU 的类型与功能选择)5. Power management and ACPI options(电源管理功能)6. Bus …

【Python 随练】❀ 绘制正方形

题目&#xff1a; 画图&#xff0c;学用rectangle画方形。 简介&#xff1a; 在本篇博客中&#xff0c;我们将介绍如何使用Python的绘图库来画方形。我们将使用rectangle函数来绘制方形&#xff0c;并提供一个完整的代码示例来演示其用法。 绘制方形&#xff1a; 要绘制方…

Dom4j在某节点上添加已有的Element节点

需求&#xff1a;有两个xml文件需要解析&#xff0c;将A文件的节点解析之后放到了一个List<Element> list的集合中了&#xff0c;然后解析B文件&#xff0c;将list的内容填充到B中去。 众所周知&#xff0c;下面这段代码是可以添加一个节点元素的。 SAXReader reader n…