intel / tsffs Goto Github PK
View Code? Open in Web Editor NEWA snapshotting, coverage-guided fuzzer for software (UEFI, Kernel, firmware, BIOS) built on SIMICS
Home Page: https://intel.github.io/tsffs/
License: Apache License 2.0
A snapshotting, coverage-guided fuzzer for software (UEFI, Kernel, firmware, BIOS) built on SIMICS
Home Page: https://intel.github.io/tsffs/
License: Apache License 2.0
All of our documentation assumes users are using ISPM from the command line. Many people prefer the GUI, especially on Windows. Documentation should be added to cover creating a project for fuzzing using the ISPM GUI.
For some use cases, it would be nice to allow having multiple harnesses compiled into the same target software and selectively enable them at run-time. There are a few ways we can do this:
n
of the magic instruction. This is problematic on some architectures, for example ARM Thumb-2, n <= 12
.MAGIC_START_SELECT (4)
this will be OK. Extended stop harnesses already include a way to communicate a value back to the fuzzer, so only start harnesses need to be extended.Should be possible to support custom mutators like libafl_libfuzzer does.
Repro currently does nothing if it is run a second time with a different input. Instead, it should restart the repro process with the new input.
Some enhancements for repro mode:
@tklengyel any other ideas for enhancements to add onto this?
Repro mode has had a regression in rev-exec (and possibly snapshot) modes where the repro requested testcase is not actually the testcase written to memory.
RISC-V has a public SIMICS package, so it makes sense as the second architecture to support.
Changes required:
We've had several requests to re-enable the fuzzing GUI/TUI including output of additional state information like current coverage. This feature used to exist, but needs to be reworked from its previous setup to be re-enabled.
There are no examples for fuzzing the Linux kernel or userland apps on Linux. We should add examples for fuzzing a kernel module on Clear Linux as well as a user-land Linux application.
https://github.com/intel/tsffs/tree/main/simics-api-sys/scripts does not have README file.
but the above URL mentioned UpdateBindings.md file.
Concolic/symbolic tracing of executions and path constraint solving for passing hard checks.
ref: https://godbolt.org/z/n11PbaKan, thanks @elnardu for pointing this out.
Casting a pointer from Box::into_raw
to a raw pointer is invalid in some scenarios. We need to evaluate whether our usage of this pattern is valid in the following usages:
tsffs/simics-fuzz/src/fuzzer/mod.rs
Line 313 in 0ee60dc
tsffs/simics-api/src/safe/base/attr_value.rs
Line 151 in 0ee60dc
If usage is invalid, we need to fix it (this may be invalid on non-linux64 and non-windows, in which case it should still be fixed even though SIMICS does not support those platforms). If not, each case needs a // NOTE:
describing why it is OK.
Full-propagation taint tracking enables some very powerful mutations during fuzzing. We can easily support taint propagation by grabbing instructions on the fly in hit_count
tracing mode.
The cycle base API should be provided via the high level bindings in the simics-api crate to enable granular speed and iteration control and tracking.
x86-32 is ostensibly supported, but there is no test case/example provided. We should provide a 32-bit only example booting the QSP-x86 platform in 32-bit mode and running a 32-bit UEFI application on it.
TSFFS is perfectly capable of fuzzing binary-only UEFI targets with some small patches to the binary, we should add an example of how this can be done.
Stop harnesses are not ignored if no start has occurred yet, leading to the fuzzer attempting to cancel events and restart the fuzz loop that has not started yet. Checks for running state should be added in modules/tsffs/src/tsffs/src/haps/mod.rs
.
We should enable a pair of APIs which looks like:
@tsffs.iface.tsffs.set_testcase_handler(testcase_handler)
Where testcase_handler
is a Callable[[bytes], None]
which is called with the testcase input. testcase_handler
is then responsible for dispatching the testcase wherever is appropriate. In particular, it should not attempt to start/stop the fuzzing loop, it should only handle the testcase. This has the effect of separating the testcase handling logic from the fuzz loop logic, but requires a "blind start" API to be enabled.
@tsffs.iface.tsffs.start()
This API would take a snapshot through the TSFFS snapshot handling sequence, without handling testcases or buffers at all. When a new testcase is generated, it will be passed to the testcase handler.
Report generation in common format(s) should be added. After exit, the fuzzer should output or update an existing report in one of one or more supported formats.
simics-fuzz
crateThe example instructions are using non-orthodox ways to set up the Simics project--package association.
For example: https://github.com/intel/tsffs/blob/main/docs/Requirements.md:
$ "${SIMICS_HOME}/simics-6.0.169/bin/project-setup" ./test-micro-checkpoints
Project created successfully
This should be accomplished using the documented addon-manager
script. Or even better, starting with setting up the project based on Public Simics using the Intel Simics Package Manager (ISPM). Since the later page https://github.com/intel/tsffs/blob/main/docs/Setup.md does use the public Simics as an example, maybe that could be moved up to the start of the docs?
The instructions on the https://github.com/intel/tsffs/blob/main/docs/Setup.md page are also missing how to set up a project pointing at the installed public release. As documented on https://www.intel.com/content/www/us/en/developer/articles/guide/simics-simulator-installation.html, it should be enough to add a --create-project
option to the ispm CLI invocation.
SIMICS supports loaded object detection for UEFI, kernels, and userland apps on supported OS-awareness operating systems (i.e. Clear Linux). Catching the object that is loaded when the harness is hit is required for:
We should enable loaded object detection with a callback to the module and/or fuzzer frontend when objects are loaded, with their type.
Enabling cargo install --git https://github.com/intel/tsffs
will enable further adoption.
This requires:
SIMICS_HOME
search process to use an env var or other configurationtsffs_module
source to the OUT_DIR
cache for use during project module compilationEnable installation of TSFFS with ISPM to facilitate easier installation and distribution.
We previously had a feature where -C
could be passed to enable distributed fuzzing. This isn't possible now, because of how we distribute as a SIMICS package, but we can develop a simple client which will connect via LLMP to the local fuzzers, start local fuzzers, etc. This will also re-enable the AFL-style TUI.
I test the manual-example, the START_ADDRESS and STOP_ADDRESS refer to this page:
https://github.com/intel/tsffs/blob/main/tests/rsrc/x86_64-uefi/test.c
so:
START_ADDRESS=0x18000117c
STOP_ADDRESS=0x18000127a
Like this,but I still get an error:
$ vim fuzz.simics
@simenv.start_addr = int(open(0x180001247).read().strip(), 16)
@simenv.stop_addr = int(open(0x180001280).read().strip(), 16)
$ ./simics -no-gui --no-win --batch-mode fuzz.simics
What should I do?
SIMICS supports running on Windows, there are some small blockers to building and running TSFFS on Windows currently due to assumptions about:
Once these issues are solved, TSFFS can run on windows and linux.
Provide options to enable deduplication of solutions:
In CI there is a race or some other failure going on, only itermittently and only in the hosted runner: ref.
Thanks a lot for this tool and its detailed documentation which make it easy to get started.
A few things I noticed while following the provided instructions:
libXpm
and gtk2
to the list of dependencies on https://intel.github.io/tsffs/setup/linux.html#install-local-dependenciestest.efi
to test micro-checkpoints, but the sample output ("Working...") corresponds to HelloWorld.efi
from the tutorial section. It is a good thing to prefer test.efi here (since it doesn't require docker to compile), you should just update the text to mention the expected output is "4141414141414141" rather than "Working..."./build.sh
rather than ninja
to build, otherwise the tsffs header is missing and linking fails.Add a simple option:
@tsffs.iface.tsffs.set_use_initial_buffer_as_corpus(True)
To use the initial contents of the harnessed buffer as the first seed instead of randomly generating alphanum inputs.
Sanitizer support is tricky, because it depends on the operating system, which UEFI/BIOS doesn't have. Some testing and some possible implementation steps:
When the simulator takes a long time to get to its first fuzzing iteration (this is common, because the BIOS in the simulator can take several minutes to boot to UEFI shell) the LLMP client can time out, which shows up as a double shutdown of the fuzzer and causes a lot of problems.
Add a stop
in the SIMICS script after initializing the fuzzer and wait for it to break.
Enable the llmp_debug
feature and look for the message Client #{i} timed out. Removing.
.
The root cause is this 5-minute timeout here.
This should be fixed upstream by adding an option to LlmpBroker
for the timeout duration, and it should be set to a long value.
With upcoming SIMICS Rust API improvements, the fuzzer module will become checkpointable. This should be implemented when possible.
Can tsffs fuzz test virtual machines device?eg:Citrix adc,Cisco ASA,and so on. if sure, Can you provide a example booting the vm platform in and running a special application on it.
Thanks @richinseattle for reporting. System is WSL2, which may or may not be relevant.
after 12 seconds, using anything other than single core, this happens most of the time but on rare occasion managed to work
(base) rjohnson@codex:~/tsffs$ RUST_BACKTRACE=1 cargo run --release --features=6.0.169 -- -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-s
olution/ -l ERROR -t -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi -f examp
les/x509-parse/rsrc/app.py:%simics%/scripts/app.py -f examples/x509-parse/rsrc/app.yml:%simics%/scripts/app.yml -f examples/x509-parse/
rsrc/minimal_boot_disk.craff:%simics%/targets/x509-parse/minimal_boot_disk.craff -f examples/x509-parse/rsrc/run_uefi_app.nsh:%simics%/ta
rgets/x509-parse/run_uefi_app.nsh -f examples/x509-parse/rsrc/run-uefi-app.simics:%simics%/targets/x509-parse/run-uefi-app.simics -x CO
NFIG:%simics%/scripts/app.yml
warning: skipping duplicate package `demo` found at `/home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/utils/gdb_qemu/demo`
warning: skipping duplicate package `libfuzzer_libpng_launcher` found at `/home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/fuzzers/libfuzzer_libpng_launcher`
Finished release [optimized + debuginfo] target(s) in 0.13s
Running `target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -t -C 2 -P '2096:6.0.70' -f 'examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi' -f 'examples/x509-parse/rsrc/app.py:%simics%/scripts/app.py' -f 'examples/x509-parse/rsrc/app.yml:%simics%/scripts/app.yml' -f 'examples/x509-parse/rsrc/minimal_boot_disk.craff:%simics%/targets/x509-parse/minimal_boot_disk.craff' -f 'examples/x509-parse/rsrc/run_uefi_app.nsh:%simics%/targets/x509-parse/run_uefi_app.nsh' -f 'examples/x509-parse/rsrc/run-uefi-app.simics:%simics%/targets/x509-parse/run-uefi-app.simics' -x 'CONFIG:%simics%/scripts/app.yml'`
thread '<unnamed>' panicked at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/ui.rs:523:18:
called `Option::unwrap()` on a `None` value
stack backtrace:
0: rust_begin_unwind
at /rustc/ca2b74f1ae5075d62e223c0a91574a1fc3f51c7c/library/std/src/panicking.rs:619:5
1: core::panicking::panic_fmt
at /rustc/ca2b74f1ae5075d62e223c0a91574a1fc3f51c7c/library/core/src/panicking.rs:72:14
2: core::panicking::panic
at /rustc/ca2b74f1ae5075d62e223c0a91574a1fc3f51c7c/library/core/src/panicking.rs:127:5
3: core::option::Option<T>::unwrap
at /rustc/ca2b74f1ae5075d62e223c0a91574a1fc3f51c7c/library/core/src/option.rs:935:21
4: libafl::monitors::tui::ui::TuiUI::draw_process_timing_text
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/ui.rs:523:18
5: libafl::monitors::tui::ui::TuiUI::draw_client_ui
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/ui.rs:290:9
6: libafl::monitors::tui::ui::TuiUI::draw
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/ui.rs:128:9
7: libafl::monitors::tui::run_tui_thread::{{closure}}::{{closure}}
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/mod.rs:567:31
8: ratatui::terminal::Terminal<B>::draw
at /home/rjohnson/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ratatui-0.23.0/src/terminal.rs:292:9
9: libafl::monitors::tui::run_tui_thread::{{closure}}
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/monitors/tui/mod.rs:567:13
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
also happened without tui tho too I think, let me test without tui it just seems to hang but does not run and emit fuzzing output like with single core
It runs the initial script ..
Running command: set -v UEFI_APP_ON_HOST "/tmp/projecttmp.RO1LoLdL/targets/x509-parse/X509Parse.efi"
Running command: set -v UEFI_APP_NODIR "X509Parse.efi"
Running command: SimicsAgent.efi --download "/tmp/projecttmp.RO1LoLdL/targets/x509-parse/run_uefi_app.nsh"
Running command: set -v UEFI_APP_ON_HOST "/tmp/projecttmp.RO1LoLdL/targets/x509-parse/X509Parse.efi"
Running command: set -v UEFI_APP_NODIR "X509Parse.efi"
Running command: "run_uefi_app.nsh"
Running command: SimicsAgent.efi --download "/tmp/projecttmp.RO1LoLdL/targets/x509-parse/run_uefi_app.nsh"
Running command: "run_uefi_app.nsh"
[matic0 info] The Simics agent has terminated.
[matic0 info] disconnected from UEFI0 (0x1b90f02e10d5a84c)
[matic0 info] The Simics agent has terminated.
[matic0 info] disconnected from UEFI0 (0x1b90f02e10d5a84c)
[matic1 info] The Simics agent has terminated.
[matic1 info] disconnected from UEFI1 (0x1b90f02e10d61ca9)
[matic1 info] The Simics agent has terminated.
[matic1 info] disconnected from UEFI1 (0x1b90f02e10d61ca9)
stuck in llmp. on the 2nd thread its in accept4()
#4 libafl_bolts::llmp::LlmpBroker<libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider>::loop_with_timeouts<libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider, libafl::events::llmp::{impl#0}::broker_loop::{closure_env#0}<libafl::inputs::bytes::BytesInput, libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider>> (self=0x7fffffff78b8, timeout=<optimized out>, sleep_time=..., on_new_msg_or_timeout=<optimized out>)
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl_bolts/src/llmp.rs:2290
#5 libafl::events::llmp::LlmpEventBroker<libafl::inputs::bytes::BytesInput, libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider>::broker_loop<libafl::inputs::bytes::BytesInput, libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider> (self=0x7fffffff78b0)
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/events/llmp.rs:178
#6 libafl::events::llmp::{impl#23}::launch::{closure#0}<libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl::state::StdState<libafl::inputs::bytes::BytesInput, libafl::corpus::cached::CachedOnDiskCorpus<libafl::inputs::bytes::BytesInput>, libafl_bolts::rands::RomuDuoJrRand, libafl::corpus::ondisk::OnDiskCorpus<libafl::inputs::bytes::BytesInput>>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider> (broker=..., remote_broker_addr=...)
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/events/llmp.rs:1171
#7 0x000055555584e40d in libafl::events::llmp::RestartingMgr<libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl::state::StdState<libafl::inputs::bytes::BytesInput, libafl::corpus::cached::CachedOnDiskCorpus<libafl::inputs::bytes::BytesInput>, libafl_bolts::rands::RomuDuoJrRand, libafl::corpus::ondisk::OnDiskCorpus<libafl::inputs::bytes::BytesInput>>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider>::launch<libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl::state::StdState<libafl::inputs::bytes::BytesInput, libafl::corpus::cached::CachedOnDiskCorpus<libafl::inputs::bytes::BytesInput>, libafl_bolts::rands::RomuDuoJrRand, libafl::corpus::ondisk::OnDiskCorpus<libafl::inputs::bytes::BytesInput>>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider> (self=0x7fffffff90a0)
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/events/llmp.rs:1208
#8 0x000055555584a082 in libafl::events::launcher::Launcher<&mut simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#0}, libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl::state::StdState<libafl::inputs::bytes::BytesInput, libafl::corpus::cached::CachedOnDiskCorpus<libafl::inputs::bytes::BytesInput>, libafl_bolts::rands::RomuDuoJrRand, libafl::corpus::ondisk::OnDiskCorpus<libafl::inputs::bytes::BytesInput>>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider>::launch<&mut simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#0}, libafl::monitors::multi::MultiMonitor<simics_fuzz::fuzzer::{impl#1}::launch::{closure_env#2}>, libafl::state::StdState<libafl::inputs::bytes::BytesInput, libafl::corpus::cached::CachedOnDiskCorpus<libafl::inputs::bytes::BytesInput>, libafl_bolts::rands::RomuDuoJrRand, libafl::corpus::ondisk::OnDiskCorpus<libafl::inputs::bytes::BytesInput>>, libafl_bolts::shmem::unix_shmem::default::CommonUnixShMemProvider> (self=0x7fffffff86d0)
at /home/rjohnson/.cargo/git/checkouts/libafl-c33dc6f5ec2f7a70/defe908/libafl/src/events/launcher.rs:240
#9 simics_fuzz::fuzzer::SimicsFuzzer::launch (self=0x7fffffffb2e0) at simics-fuzz/src/fuzzer/mod.rs:841
#10 0x0000555555843603 in simics_fuzz::fuzzer::SimicsFuzzer::cli_main (args=...) at simics-fuzz/src/fuzzer/mod.rs:229
#11 0x00005555555cabb7 in simics_fuzz::main () at simics-fuzz/src/bin/simics-fuzz.rs:10
the worker processes run but the main ui seems to not be hooking up properly
rjohnson 18549 0.4 0.0 105600 16356 pts/0 Sl+ 18:40 0:01 | \_ ./target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi -f examp
rjohnson 18749 0.0 0.0 297072 9832 pts/0 S+ 18:40 0:00 | \_ ./target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi -f e
rjohnson 18752 66.0 0.2 1190056 254148 pts/0 Sl+ 18:40 4:35 | | \_ ./target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi
rjohnson 18750 0.0 0.0 297072 9836 pts/0 S+ 18:40 0:00 | \_ ./target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi -f e
rjohnson 18753 59.0 0.2 1108876 252664 pts/0 Sl+ 18:40 4:06 | \_ ./target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Parse.efi
rjohnson 18501 0.0 0.0 297072 11384 pts/0 S 18:38 0:00 \_ /home/rjohnson/tsffs/target/release/simics-fuzz -c /tmp/x509-parse-corpus/ -o /tmp/x509-parse-solution/ -l ERROR -C 2 -P 2096:6.0.70 -f examples/x509-parse/rsrc/X509Parse.efi:%simics%/targets/x509-parse/X509Par
rjohnson 18505 53.4 0.2 1108876 269408 pts/0 Sl 18:38 4:41 \_ /home/rjohnson/tsffs/target/release/simics-fuzz -c /tmp/x509-parse-corpus/
was trying to show load there
I attached with gdb and they step through
I test the platform BIOS fuzzer, it‘s report :
Traceback (most recent call last):
File "<qsp-uefi-custom.target.yml.include:14>", line 1, in <module>
AttributeError: <the simics-uefi 'qsp.simics_uefi'> has no attribute 'video_mode'
[/home/gandalf/simics/tsffs/examples/tutorials/edk2-simics-platform/project/targets/qsp-x86/qsp-uefi-custom.target.yml.include:14] error in '@' command
[/home/gandalf/simics/tsffs/examples/tutorials/edk2-simics-platform/project/fuzz2.simics:12] error in 'load-target' command
Error - interrupting script.
Add an interface method that allows starting the fuzzer with a pointer to the size and the initial size instead of requiring the initial size to be located at *ptr
.
I am running the fuzzer inside a docker container, but for some reason when hit CTRL-C to kill tsffs to reproduce a crash from the simics terminal after about 30secs the simics process gets killed. I can usually reproduce one solution before it kills the program. This only happens when running with a custom bios image, but when I use the default one I don't have the problem and am able to reproduce the results just fine.
This wasn't a problem with the older version of tsffs I was testing on. The problem is most likely on my end, but I wasn't sure if this has been seen by anyone else or if there are any ideas on what I might be doing wrong?
TSFFS builds and runs in docker already in CI, we should provide a Dockerfile that can be used on Windows and Linux for running TSFFS.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.