I'm trying to write code similar to the following:
let [a; b] =
(* body *)
[1; 2]
And I want to disable warning # 8 just for the pattern [a; b] and not for the body or for anything outside of the let. I've tried to put the warning attribute to disable the warning, but none of the below work:
let[#warning "-8"] [a[#warning "-8"];b[#warning "-8"]] [#warning "-8"] =
[1;2][#warning "-8"]
[##ocaml.warning "-8"]
P.S. I'm not really writing this code, but am experimenting with a custom PPX preprocessor. So a convoluted but working example is acceptable.
Local disabling of warnings with [#warning "…"] and [##warning "…"]is not well supported for OCaml version anterior to 4.06.0 . For such version, one possibility might be to use enclosing[###warning ""] attribute:
[###warning "-8"]
let [a;b] = [1;2]
[###warning "+8"]
but this also deactivate the warning inside the body.
If you are generating the code and know statiscally the size of the list, another option might be to use a tuple for the binding (aka let (a,b)= …)?
Related
I am editing a Groovy (3.0.10) script and I am getting a syntactic error that I do not understand:
When I try this in GroovyConsole, it seems to work just fine.
Why is IntelliJ IDEA complaining? This is with IntelliJ IDEA 2022.1.1.
The snippet in text:
final java.nio.file.Path p;
p.traverse(type: FileType.FILES, nameFilter: ~/^\.deployment$/, maxDepth: 1) { final Path dotDeploymentPath ->
println dotDeploymentPath
}
UPDATE 1
I actually got the same error from Groovy when running the script in our product:
Script4.groovy: 59: [Static type checking] - Cannot call java.nio.file.Path#traverse(java.util.Map <java.lang.String, java.lang.Object>, groovy.lang.Closure) with arguments [java.util.LinkedHashMap <java.lang.String, java.io.Serializable>, groovy.lang.Closure]
# line 59, column 9.
extensionsPath.traverse(type: FileType.FILES, nameFilter: ~/^\.deployment$/, maxDepth: 1) { final Path dotDeploymentPath ->
^
UPDATE 2
I ended up with this which seems to work just fine. I still don't understand why Groovy does not like the options as arguments of the call.
def final traverseOptions = [type: FileType.FILES, nameFilter: ~/^\.deployment$/, maxDepth: 1] as Map<String, Object>;
extensionsPath.traverse(traverseOptions) { final Path dotDeploymentPath ->
So I figured this out. The issue was that I used #CompileStatic at the top of my class. I used #CompileStatic because I misunderstood what it does. I thought it were similar to saying static class in Java. But that is not what it does. What it does instead is this, from the docs: This will let the Groovy compiler use compile time checks in the style of Java then perform static compilation, thus bypassing the Groovy meta object protocol.
(This shows how important it is to provide self contained test case. I should have known better.)
I am a student studying angr, first time.
I'm watching the code in this url.
https://github.com/Dvd848/CTFs/blob/master/2020_GoogleCTF/Beginner.md
import angr
import claripy
FLAG_LEN = 15
STDIN_FD = 0
base_addr = 0x100000 # To match addresses to Ghidra
proj = angr.Project("./a.out", main_opts={'base_addr': base_addr})
flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(FLAG_LEN)]
flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) # Add \n for scanf() to accept the input
state = proj.factory.full_init_state(
args=['./a.out'],
add_options=angr.options.unicorn,
stdin=flag,
)
# Add constraints that all characters are printable
for k in flag_chars:
state.solver.add(k >= ord('!'))
state.solver.add(k <= ord('~'))
simgr = proj.factory.simulation_manager(state)
find_addr = 0x101124 # SUCCESS
avoid_addr = 0x10110d # FAILURE
simgr.explore(find=find_addr, avoid=avoid_addr)
if (len(simgr.found) > 0):
for found in simgr.found:
print(found.posix.dumps(STDIN_FD))
https://github.com/google/google-ctf/tree/master/2020/quals/reversing-beginner/attachments
Which is the answer of googlectf beginner.
But, the above code does not work. It doesn't give me the answer.
I want to know why the code is not working.
When I execute this code, the output was empty.
I run the code with python3 in Ubuntu 20.04 in wsl2
Thank you.
I believe this script isn't printing anything because angr fails to find a solution and then exits. You can prove this by appending the following to your script:
else:
raise Exception('Could not find the solution')
If the exception raises, a valid solution was not found.
In terms of why it doesn't work, this code looks like copy & paste from a few different sources, and so it's fairly convoluted.
For example, the way the flag symbol is passed to stdin is not ideal. By default, stdin is a SimPackets, so it's best to keep it that way.
The following script solves the challenge, I have commented it to help you understand. You will notice that changing stdin=angr.SimPackets(name='stdin', content=[(flag, 15)]) to stdin=flag will cause the script to fail, due to the reason mentioned above.
import angr
import claripy
base = 0x400000 # Default angr base
project = angr.Project("./a.out")
flag = claripy.BVS("flag", 15 * 8) # length is expected in bits here
initial_state = project.factory.full_init_state(
stdin=angr.SimPackets(name='stdin', content=[(flag, 15)]), # provide symbol and length (in bytes)
add_options ={
angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS
}
)
# constrain flag to common alphanumeric / punctuation characters
[initial_state.solver.add(byte >= 0x20, byte <= 0x7f) for byte in flag.chop(8)]
sim = project.factory.simgr(initial_state)
sim.explore(
find=lambda s: b"SUCCESS" in s.posix.dumps(1), # search for a state with this result
avoid=lambda s: b"FAILURE" in s.posix.dumps(1) # states that meet this constraint will be added to the avoid stash
)
if sim.found:
solution_state = sim.found[0]
print(f"[+] Success! Solution is: {solution_state.posix.dumps(0)}") # dump whatever was sent to stdin to reach this state
else:
raise Exception('Could not find the solution') # Tell us if angr failed to find a solution state
A bit of Trivia - there are actually multiple 'solutions' that the program would accept, I guess the CTF flag server only accepts one though.
❯ echo -ne 'CTF{\x00\xe0MD\x17\xd1\x93\x1b\x00n)' | ./a.out
Flag: SUCCESS
The remark site has a link to an AST explorer for the output of remark - https://astexplorer.net/#/gist/0a92bbf654aca4fdfb3f139254cf0bad/ffe102014c188434c027e43661dbe6ec30042ee2
What I cannot find is how to do the parsing to AST - all the examples convert to html.
I have this code
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkGfm from 'remark-gfm' // git flavoured markdown
const content = `
# My header
This is my content
- abc
- def
`;
unified()
.use(remarkParse)
.use(remarkGfm)
.process('# Hi\n\n*Hello*, world!')
.then((file) => {
console.log(String(file))
})
but am getting a couple of errors here that I do not know how to get around
[remark-gfm] Warning: please upgrade to remark 13 to use this plugin
file:///markdown/node_modules/unified/lib/index.js:520
throw new TypeError('Cannot `' + name + '` without `Compiler`')
^
TypeError: Cannot `process` without `Compiler`
You almost have it. Below I've simplified your code, removing unused and unnecessary parts.
import {unified} from 'unified'
import remarkParse from 'remark-parse'
let myResult = unified()
.use(remarkParse)
.parse('# Hi\n\n*Hello*, world!');
console.log(JSON.stringify(myResult, null, " "));
According to ChristianMurphy's GitHub Q/A:
unified.process() will try to take text, turn it into an AST, and back into text.
For your stated purpose, "...parsing to AST [JSON]", you don't need or want the "full-cycle process" that unified.process() is failing to complete, TypeError: Cannot 'process' without 'Compiler'. You merely want to parse the input and emit the syntax tree (AST) as JSON. The error here is because process(), after parsing your input (markdown string) and turning it into a syntax tree (AST), is then trying to "compile" it to some output format. However, you haven't supplied a compiler. But, as I understand your post, you don't need or want to compile the syntax tree into another output (language). So, change from process() to parse() and emit the resulting syntax tree as JSON.
I've followed quite a bit of the documentation and tried to reuse an example, but I can't get my code to work.
My Cargo.toml looks like this:
[package]
name = "Blahblah"
version = "0.3.0"
authors = ["ergh <derngummit#ahwell.com"]
[dependencies]
[[bin]]
name = "target"
path = "src/main.rs"
[features]
default=["mmap_enabled"]
no_mmap=[]
mmap_enabled=[]
I'd like to test my code locally with a different buffer origin than mmap based on what feature configuration I pass to the cargo build command. I have this in my code:
if cfg!(mmap_enabled) {
println!("mmap_enabled bro!");
...
}
if cfg!(no_mmap) {
println!("now it's not");
...
}
The compiler doesn't see the code in either of the if statement bodies, so I know that both of the cfg! statements are evaluating to false. Why?
I've read Conditional compilation in Rust 0.10? and I know it's not an exact duplicate because I'm looking for a functioning example.
The correct way to test for a feature is feature = "name", as you can see in the documentation you linked if you scroll a bit:
As for how to enable or disable these switches, if you’re using Cargo,
they get set in the [features] section of your Cargo.toml:
[features]
# no features by default
default = []
# Add feature "foo" here, then you can use it.
# Our "foo" feature depends on nothing else.
foo = []
When you do this, Cargo passes along a flag to rustc:
--cfg feature="${feature_name}"
The sum of these cfg flags will determine which ones get activated,
and therefore, which code gets compiled. Let’s take this code:
#[cfg(feature = "foo")]
mod foo {
}
In your case using the cfg! macro, this would map to cfg!(feature = "foo").
I need to load, alter and write the code in a mix.exs file. I want to be able to load the file, write the dependencies and write the file.
I start with:
defmodule Elixir_2ndTest.Mixfile do
use Mix.Project
def project do
[app: :elixir_2nd_test,
version: "0.0.1",
elixir: "~> 1.2",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
description: description(),
deps: deps]
end
def application do
[applications: [:logger]]
end
defp deps do
[]
end
end
And I need to end up with (the only difference is in the deps fun):
defmodule Elixir_2ndTest.Mixfile do
use Mix.Project
def project do
[app: :elixir_2nd_test,
version: "0.0.1",
elixir: "~> 1.2",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
description: description(),
deps: deps]
end
def application do
[applications: [:logger]]
end
defp deps do
[{:httpoison, "~> 0.8.3"}]
end
end
The dependencies come from a different build system (I cannot use hex directly form the public internet, so I use it in OFFLINE mode and drop the dependencies in .hex/
I know what teh depenencies and what the versions are an need to insert them in the deps function (in this case httpoison 0.8.3).
If my understanding is correct this should be possible by loading the file, quoting, altering, unquoting.
This is what I have up until this point:
{:ok, body} = File.read("mix.exs")
{:ok, ast} = Code.string_to_quoted(body)
Any pointer on how I can alter the ast and write it back would be appreciated.
It won't look exactly the same, but you can use Macro.to_string to convert the ast back to elixir code.
I was playing around with using my library PhStTransform to modify the ast and convert it back to code. Here's a very simple example from the PhStTransform test library.
test "transform quote do output" do
data = quote do: Enum.map(1..3, fn(x) -> x*x end)
data_transform = quote do: Enum.map(1..3, fn(y) -> y*y end)
replace_x = fn(a, _d ) ->
case a do
:x -> :y
atom -> atom
end
end
potion = %{ Atom => replace_x }
assert PhStTransform.transform(data, potion) == data_transform
end
What that does is convert all references to :x in the ast into :y. You'd need to be a bit more clever with writing the potion for PhStTransform, but I think it should be possible. PhStTransform is in hex.pm.
https://hex.pm/packages/phst_transform
I'm not an Elixir expert, but I know about transforming source code; see my bio.
If you have access to the AST as a data structure, you can always write procedural code to climb over it and hack at where you want something different. I assume if Elixir will give you the AST, it will give you access/modification procedures for working with it. This is compiler 101.
That's usually NOT pretty code to write or maintain. And, it may not be enough: you often need more than just the AST to do serious analysis and transformation. See my essay on Life After Parsingl. Think of this as compiler 102.
One the first stumbling blocks is regenerating text from the AST. Here is my SO discussion on how to prettyprint an AST, and why it is harder than it looks: https://stackoverflow.com/a/5834775/120163
(Sounds like Fred the Magic Wonder Dog didn't think what Elixir offered was enough and is inventing his own extensions to make this easier.).