summaryrefslogtreecommitdiff
path: root/.github/workflows/ci.yml
blob: 3011b94270207535dd5db7421644c3ef11d7083a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
name: Continuous Integration
on: [push, pull_request]

jobs:
  test:
    strategy:
      matrix:
        python_version: ['2.7', '3.10']
        os: [ubuntu-latest]
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 20

    - name: Git History
      run: |
        git fetch origin
        git log --oneline --graph -10

    - name: Cache for pip
      uses: actions/cache@v3
      id: cache-pip
      with:
        path: ~/.cache/pip
        key: ${{ matrix.os }}-cache-pip

    - name: Set up Python ${{ matrix.python_version }}
      if: matrix.python_version != '2.7'
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python_version }}

    - name: Set up Python 2.7
      if: matrix.python_version == '2.7'
      run: |
        sudo apt-get update
        sudo apt-get install -y \
          python2.7 python2.7-dev python2-pip-whl
        sudo ln -sf python2.7 /usr/bin/python
        export PYTHONPATH=`echo /usr/share/python-wheels/pip-*py2*.whl`
        sudo --preserve-env=PYTHONPATH python -m pip install --upgrade pip setuptools wheel
        sudo chown -R $USER /usr/local/lib/python2.7


    - name: Verify tag against version
      if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
      env:
        GITHUB_REF: ${{ github.event.ref }}
      run: |
        set -x
        GITHUB_TAG=${GITHUB_REF#refs/tags/}
        echo "$GITHUB_TAG" | grep -E '^[0-9.]*(beta[0-9])?$'
        vsetup=$(grep -o "version\\s*=\\s*[\"'].*[\"'],$" setup.py | grep -o "[0-9][^\"']*")
        vpwnlib=$(grep -o "__version__\\s*=\\s*[\"'].*[\"']$" pwnlib/version.py | grep -o "[0-9][^\"']*")
        [ "$vsetup" = "$vpwnlib" ]
        [ "$GITHUB_TAG" = "$vsetup" ]

    - name: Install Linux dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 \
          ash bash-static dash ksh mksh zsh \
          python3-rpyc \
          gdb gdbserver socat \
          binutils-multiarch qemu-user-static \
          binutils-aarch64-linux-gnu \
          binutils-arm-linux-gnueabihf \
          binutils-mips-linux-gnu \
          binutils-msp430 \
          binutils-powerpc-linux-gnu \
          binutils-s390x-linux-gnu \
          binutils-sparc64-linux-gnu \
          gcc-multilib \
          libc6-dbg \
          elfutils \
          patchelf
      
    - name: Testing Corefiles
      run: |
        ulimit -a
        ulimit -c unlimited
        cat /proc/sys/kernel/core_pattern
        cat /proc/sys/kernel/core_uses_pid
        ( cd $(mktemp -d); sh -c 'kill -11 $$' || true; ls -la ./*core* /var/crash/*.crash /var/lib/apport/coredump/core*) || true

    - name: Set up SSH
      run: |
        travis/ssh_setup.sh

    - name: Install dependencies
      run: |
        pip install --upgrade pip
        pip install --upgrade wheel build
        pip install --upgrade flake8 appdirs
        pip install --upgrade --editable .

    - name: Sanity checks
      run:  PWNLIB_NOTERM=1 python -bb -c 'from pwn import *; print(pwnlib.term.term_mode)'

    - name: Install documentation dependencies
      run: pip install -r docs/requirements.txt

    - name: Manually install non-broken Unicorn
      if:   matrix.python_version == '2.7'
      run:  pip install unicorn==2.0.0rc7

    - name: Disable yama ptrace_scope
      run: |
        echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # required by some gdb doctests

    - name: Coverage doctests
      run: |
        PWNLIB_NOTERM=1 python -bb -m coverage run -m sphinx -b doctest docs/source docs/build/doctest

    - name: Coverage running examples
      run: |
        export TERM=linux
        set -x
        python -bb travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit.py
        python -bb travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit2.py || : # can fail randomly?
        python -bb -m coverage run examples/asm.py
        python -bb -m coverage run examples/asm.py
        python -bb -m coverage run examples/text.py
        # for f in examples/sigreturn_corefile_*.py; do coverage run "$f"; done # XXX something is wrong

    - name: Coverage running commandline tools
      run: |
        export TERM=linux
        pwn() { ( set +x; cmd=$1; shift; PYTHONUNBUFFERED=1 exec python -bb -m coverage run -m pwnlib.commandline."$cmd" "$@" ) }
        set -x

        pwn cyclic 32
        pwn cyclic -l 0x62616161
        pwn cyclic -a ab
        echo

        pwn shellcraft --list |tail
        pwn shellcraft -l --syscalls |tail
        pwn shellcraft -l execve
        pwn shellcraft --show i386.linux.loader_append
        pwn shellcraft -f asm --color amd64.linux.sh
        pwn shellcraft -f elf amd64.linux.syscalls.exit 0 </dev/null |pwn hex
        pwn shellcraft -f i   --color amd64.linux.cat /etc/passwd </dev/null
        pwn shellcraft -f c   amd64.linux.syscalls.exit 0 </dev/null
        pwn shellcraft -f str aarch64.linux.sh </dev/null
        pwn shellcraft -abr -f elf -o /dev/null amd64.linux.cat /etc/passwd </dev/null
        pwn shellcraft -nzr thumb.linux.syscalls.execve /bin/cat '["/bin/cat", "/etc/os-release"]' </dev/null
        pwn shellcraft -fp aarch64.trap

        pwn disasm --color ff3424c3ebfe
        pwn asm -f hex nop

        pwn hex ABCD
        pwn hex ABCD --separator ' '
        pwn hex ABCD --prefix '\x'
        pwn hex ABCD -p '0x' -s ' '

        pwn hex abcd
        pwn unhex 4141 4141

        cat /dev/urandom | pwn phd --color -c 256 -s 2
        pwn phd -l 0x3d --color=always /etc/os-release

        pwn checksec /bin/bash

        pwn errno 2
        pwn errno -1
        pwn errno EADDRINUSE

        pwn constgrep -c freebsd -m ^PROT_ '3 + 4'
        pwn constgrep ^MAP_ 0
        pwn constgrep -e O_RDWR

        pwn libcdb file /lib/x86_64-linux-gnu/libc.so.6
        pwn libcdb lookup puts 5f0 __libc_start_main_ret d0a
        pwn libcdb hash b229d1da1e161f95e839cf90cded5f719e5de308

    - name: Build source and wheel distributions
      if: matrix.python_version > '2.7'
      run: |
        python -m build

    - uses: actions/upload-artifact@v3
      with:
        name: packages
        path: dist/

    - uses: actions/upload-artifact@v3
      with:
        name: coverage
        path: .coverage*


  upload-coverage:
    runs-on: ubuntu-latest
    needs: test
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 20

    - uses: actions/download-artifact@v3
      with:
        name: coverage
        path: .

    - name: Install coveralls
      run: |
        pip install tomli coveralls

    - name: Upload coverage to coveralls.io
      run: |
        coverage combine
        COVERALLS_REPO_TOKEN=PP20MEgztXIQJJTguQwe2jeCh6Bm4lkbv coveralls


  staging-merge:
    runs-on: ubuntu-latest
    if: github.repository_owner == 'Gallopsled' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/') && endsWith(github.event.ref, '-staging')
    needs: test
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 20
    - name: Push changes to protected branch
      env:
        GITHUB_REF: ${{ github.event.ref }}
      run: |
        BRANCH=${GITHUB_REF#refs/heads/}
        TARGET=${BRANCH%-staging}
        git branch -f "$TARGET"
        git push origin "$TARGET"
        git push origin --delete "$BRANCH"


  pypi:
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
    permissions:
      id-token: write
    needs: test
    steps:
    - name: Download artifacts
      uses: actions/download-artifact@v3
      with:
        name: packages
        path: dist

    - name: Publish package
      uses: pypa/gh-action-pypi-publish@release/v1

    - if: failure()
      run: ls -R