/** Add an entry to the GeoIP table indicated by <b>family</b>, * parsing it from <b>line</b>. The format is as for geoip_load_file(). */ /*private*/ int geoip_parse_entry(const char *line, sa_family_t family) { tor_addr_t low_addr, high_addr; char c[3]; char *country = NULL; if (!geoip_countries) init_geoip_countries(); if (family == AF_INET) { if (!geoip_ipv4_entries) geoip_ipv4_entries = smartlist_new(); } else if (family == AF_INET6) { if (!geoip_ipv6_entries) geoip_ipv6_entries = smartlist_new(); } else { log_warn(LD_GENERAL, "Unsupported family: %d", family); return -1; } while (TOR_ISSPACE(*line)) ++line; if (*line == '#') return 0; if (family == AF_INET) { unsigned int low, high; if (tor_sscanf(line,"%u,%u,%2s", &low, &high, c) == 3 || tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, c) == 3) { tor_addr_from_ipv4h(&low_addr, low); tor_addr_from_ipv4h(&high_addr, high); } else goto fail; country = c; } else { /* AF_INET6 */ char buf[512]; char *low_str, *high_str; struct in6_addr low, high; char *strtok_state; strlcpy(buf, line, sizeof(buf)); low_str = tor_strtok_r(buf, ",", &strtok_state); if (!low_str) goto fail; high_str = tor_strtok_r(NULL, ",", &strtok_state); if (!high_str) goto fail; country = tor_strtok_r(NULL, "\n", &strtok_state); if (!country) goto fail; if (strlen(country) != 2) goto fail; if (tor_inet_pton(AF_INET6, low_str, &low) <= 0) goto fail; tor_addr_from_in6(&low_addr, &low); if (tor_inet_pton(AF_INET6, high_str, &high) <= 0) goto fail; tor_addr_from_in6(&high_addr, &high); } geoip_add_entry(&low_addr, &high_addr, country); return 0; fail: log_warn(LD_GENERAL, "Unable to parse line from GEOIP %s file: %s", family == AF_INET ? "IPv4" : "IPv6", escaped(line)); return -1; }
int regex_parser::process_escape(const char *re, int ptr, int_set *chars){ if (ptr==strlen(re)){ return (++ptr); //fatal("regex_parser:: process_escape: \\ in last position."); } char c=re[ptr]; int next; if(is_x(c)){ if(ptr>strlen(re)-3) fatal("regex_parser::process_escape: invalid hex escape sequence."); else if (!is_hex_digit(re[ptr+1]) || !is_hex_digit(re[ptr+2])) fatal("regex_parser::process_escape: invalid hex escape sequence."); else{ char tmp[5]; tmp[0]='0';tmp[1]=c;tmp[2]=re[ptr+1];tmp[3]=re[ptr+2]; tmp[4]='\0'; sscanf(tmp,"0x%x", &next); chars->insert(next); ptr=ptr+3; } }else if (is_oct_digit(c)){ if(ptr>strlen(re)-3) {next=escaped(c);ptr++;chars->insert(next);} //normal escape sequence else if (!is_oct_digit(re[ptr+1]) || !is_oct_digit(re[ptr+2])) {next=escaped(c);ptr++;chars->insert(next);} //normal escape sequence else{ //really an octal sequence! char tmp[5]; tmp[0]='0';tmp[1]=c;tmp[2]=re[ptr+1];tmp[3]=re[ptr+2]; tmp[4]='\0'; sscanf(tmp,"0%o", &next); chars->insert(next); ptr=ptr+3; } }else if(c=='s'){ chars->insert('\t'); chars->insert('\n'); chars->insert('\r'); chars->insert('\x0C'); chars->insert('\x20'); ptr++; }else if(c=='S'){ chars->insert('\t'); chars->insert('\n'); chars->insert('\r'); chars->insert('\x0C'); chars->insert('\x20'); chars->negate(); ptr++; }else if(c=='d'){ chars->insert('0');chars->insert('1');chars->insert('2'); chars->insert('3');chars->insert('4');chars->insert('5'); chars->insert('6');chars->insert('7');chars->insert('8'); chars->insert('9'); ptr++; }else if(c=='D'){ chars->insert('0');chars->insert('1');chars->insert('2'); chars->insert('3');chars->insert('4');chars->insert('5'); chars->insert('6');chars->insert('7');chars->insert('8'); chars->insert('9'); chars->negate(); ptr++; }else if(c=='w'){ chars->insert('_'); chars->insert('0');chars->insert('1');chars->insert('2'); chars->insert('3');chars->insert('4');chars->insert('5'); chars->insert('6');chars->insert('7');chars->insert('8'); chars->insert('9'); chars->insert('a');chars->insert('b');chars->insert('c'); chars->insert('d');chars->insert('e');chars->insert('f'); chars->insert('g');chars->insert('h');chars->insert('i'); chars->insert('j');chars->insert('k');chars->insert('l'); chars->insert('m');chars->insert('n');chars->insert('o'); chars->insert('p');chars->insert('q');chars->insert('r'); chars->insert('s');chars->insert('t');chars->insert('u'); chars->insert('v');chars->insert('w');chars->insert('x'); chars->insert('y');chars->insert('z'); chars->insert('A');chars->insert('B');chars->insert('C'); chars->insert('D');chars->insert('E');chars->insert('F'); chars->insert('G');chars->insert('H');chars->insert('I'); chars->insert('J');chars->insert('K');chars->insert('L'); chars->insert('M');chars->insert('N');chars->insert('O'); chars->insert('P');chars->insert('Q');chars->insert('R'); chars->insert('S');chars->insert('T');chars->insert('U'); chars->insert('V');chars->insert('W');chars->insert('X'); chars->insert('Y');chars->insert('Z'); ptr++; }else if(c=='W'){ chars->insert('_'); chars->insert('0');chars->insert('1');chars->insert('2'); chars->insert('3');chars->insert('4');chars->insert('5'); chars->insert('6');chars->insert('7');chars->insert('8'); chars->insert('9'); chars->insert('a');chars->insert('b');chars->insert('c'); chars->insert('d');chars->insert('e');chars->insert('f'); chars->insert('g');chars->insert('h');chars->insert('i'); chars->insert('j');chars->insert('k');chars->insert('l'); chars->insert('m');chars->insert('n');chars->insert('o'); chars->insert('p');chars->insert('q');chars->insert('r'); chars->insert('s');chars->insert('t');chars->insert('u'); chars->insert('v');chars->insert('w');chars->insert('x'); chars->insert('y');chars->insert('z'); chars->insert('A');chars->insert('B');chars->insert('C'); chars->insert('D');chars->insert('E');chars->insert('F'); chars->insert('G');chars->insert('H');chars->insert('I'); chars->insert('J');chars->insert('K');chars->insert('L'); chars->insert('M');chars->insert('N');chars->insert('O'); chars->insert('P');chars->insert('Q');chars->insert('R'); chars->insert('S');chars->insert('T');chars->insert('U'); chars->insert('V');chars->insert('W');chars->insert('X'); chars->insert('Y');chars->insert('Z'); chars->negate(); ptr++; }else{ next=escaped(c); chars->insert(next); ptr++; } return ptr; }
/** Process a 'create' <b>cell</b> that just arrived from <b>conn</b>. Make a * new circuit with the p_circ_id specified in cell. Put the circuit in state * onionskin_pending, and pass the onionskin to the cpuworker. Circ will get * picked up again when the cpuworker finishes decrypting it. */ static void command_process_create_cell(cell_t *cell, or_connection_t *conn) { or_circuit_t *circ; int id_is_high; if (we_are_hibernating()) { log_info(LD_OR, "Received create cell but we're shutting down. Sending back " "destroy."); connection_or_send_destroy(cell->circ_id, conn, END_CIRC_REASON_HIBERNATING); return; } if (!server_mode(get_options())) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received create cell (type %d) from %s:%d, but we're a client. " "Sending back a destroy.", (int)cell->command, conn->_base.address, conn->_base.port); connection_or_send_destroy(cell->circ_id, conn, END_CIRC_REASON_TORPROTOCOL); return; } /* If the high bit of the circuit ID is not as expected, close the * circ. */ id_is_high = cell->circ_id & (1<<15); if ((id_is_high && conn->circ_id_type == CIRC_ID_TYPE_HIGHER) || (!id_is_high && conn->circ_id_type == CIRC_ID_TYPE_LOWER)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received create cell with unexpected circ_id %d. Closing.", cell->circ_id); connection_or_send_destroy(cell->circ_id, conn, END_CIRC_REASON_TORPROTOCOL); return; } if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) { routerinfo_t *router = router_get_by_digest(conn->identity_digest); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received CREATE cell (circID %d) for known circ. " "Dropping (age %d).", cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created)); if (router) log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Details: nickname \"%s\", platform %s.", router->nickname, escaped(router->platform)); return; } circ = or_circuit_new(cell->circ_id, conn); circ->_base.purpose = CIRCUIT_PURPOSE_OR; circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING); if (cell->command == CELL_CREATE) { char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN); memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN); /* hand it off to the cpuworkers, and then return. */ if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) { log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; } log_debug(LD_OR,"success: handed off onionskin."); } else { /* This is a CREATE_FAST cell; we can handle it immediately without using * a CPU worker. */ char keys[CPATH_KEY_MATERIAL_LEN]; char reply[DIGEST_LEN*2]; tor_assert(cell->command == CELL_CREATE_FAST); if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) { log_warn(LD_OR,"Failed to generate key material. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; } if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) { log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; } } }
/** * Helper function to parse out a line in the measured bandwidth file * into a measured_bw_line_t output structure. * * If <b>line_is_after_headers</b> is true, then if we encounter an incomplete * bw line, return -1 and warn, since we are after the headers and we should * only parse bw lines. Return 0 otherwise. * * If <b>line_is_after_headers</b> is false then it means that we are not past * the header block yet. If we encounter an incomplete bw line, return -1 but * don't warn since there could be additional header lines coming. If we * encounter a proper bw line, return 0 (and we got past the headers). * * If the line contains "vote=0", stop parsing it, and return -1, so that the * line is ignored during voting. */ STATIC int measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line, int line_is_after_headers) { char *line = tor_strdup(orig_line); char *cp = line; int got_bw = 0; int got_node_id = 0; char *strtok_state; /* lame sauce d'jour */ if (strlen(line) == 0) { log_warn(LD_DIRSERV, "Empty line in bandwidth file"); tor_free(line); return -1; } /* Remove end of line character, so that is not part of the token */ if (line[strlen(line) - 1] == '\n') { line[strlen(line) - 1] = '\0'; } cp = tor_strtok_r(cp, " \t", &strtok_state); if (!cp) { log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } if (orig_line[strlen(orig_line)-1] != '\n') { log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } do { // If the line contains vote=0, ignore it. if (strcmpstart(cp, "vote=0") == 0) { log_debug(LD_DIRSERV, "Ignoring bandwidth file line that contains " "vote=0: %s",escaped(orig_line)); tor_free(line); return -1; } else if (strcmpstart(cp, "bw=") == 0) { int parse_ok = 0; char *endptr; if (got_bw) { log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } cp+=strlen("bw="); out->bw_kb = tor_parse_long(cp, 10, 0, LONG_MAX, &parse_ok, &endptr); if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) { log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } got_bw=1; } else if (strcmpstart(cp, "node_id=$") == 0) { if (got_node_id) { log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } cp+=strlen("node_id=$"); if (strlen(cp) != HEX_DIGEST_LEN || base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } strlcpy(out->node_hex, cp, sizeof(out->node_hex)); got_node_id=1; } } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state))); if (got_bw && got_node_id) { tor_free(line); return 0; } else if (line_is_after_headers == 0) { /* There could be additional header lines, therefore do not give warnings * but returns -1 since it's not a complete bw line. */ log_debug(LD_DIRSERV, "Missing bw or node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); return -1; } else { log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s", escaped(orig_line)); tor_free(line); return -1; } }
std::string type_constraint(const TypeConstraint &tc) { std::string typeName = tc.typeName() ? escaped(tc.typeName()) : "N"; return folly::format("{} {} ", typeName, type_flags_to_string(tc.flags())).str(); }
/* Decide if the newly received <b>commit</b> should be kept depending on * the current phase and state of the protocol. The <b>voter_key</b> is the * RSA identity key fingerprint of the authority's vote from which the * commit comes from. The <b>phase</b> is the phase we should be validating * the commit for. Return 1 if the commit should be added to our state or 0 * if not. */ STATIC int should_keep_commit(const sr_commit_t *commit, const char *voter_key, sr_phase_t phase) { const sr_commit_t *saved_commit; tor_assert(commit); tor_assert(voter_key); log_debug(LD_DIR, "SR: Inspecting commit from %s (voter: %s)?", sr_commit_get_rsa_fpr(commit), hex_str(voter_key, DIGEST_LEN)); /* For a commit to be considered, it needs to be authoritative (it should * be the voter's own commit). */ if (!commit_is_authoritative(commit, voter_key)) { log_debug(LD_DIR, "SR: Ignoring non-authoritative commit."); goto ignore; } /* Let's make sure, for extra safety, that this fingerprint is known to * us. Even though this comes from a vote, doesn't hurt to be * extracareful. */ if (trusteddirserver_get_by_v3_auth_digest(commit->rsa_identity) == NULL) { log_warn(LD_DIR, "SR: Fingerprint %s is not from a recognized " "authority. Discarding commit.", escaped(commit->rsa_identity)); goto ignore; } /* Check if the authority that voted for <b>commit</b> has already posted * a commit before. */ saved_commit = sr_state_get_commit(commit->rsa_identity); switch (phase) { case SR_PHASE_COMMIT: /* Already having a commit for an authority so ignore this one. */ if (saved_commit) { /* Receiving known commits should happen naturally since commit phase lasts multiple rounds. However if the commitment value changes during commit phase, it might be a bug so log more loudly. */ if (!commitments_are_the_same(commit, saved_commit)) { log_info(LD_DIR, "SR: Received altered commit from %s in commit phase.", sr_commit_get_rsa_fpr(commit)); } else { log_debug(LD_DIR, "SR: Ignoring known commit during commit phase."); } goto ignore; } /* A commit with a reveal value during commitment phase is very wrong. */ if (commit_has_reveal_value(commit)) { log_warn(LD_DIR, "SR: Commit from authority %s has a reveal value " "during COMMIT phase. (voter: %s)", sr_commit_get_rsa_fpr(commit), hex_str(voter_key, DIGEST_LEN)); goto ignore; } break; case SR_PHASE_REVEAL: /* We are now in reveal phase. We keep a commit if and only if: * * - We have already seen a commit by this auth, AND * - the saved commit has the same commitment value as this one, AND * - the saved commit has no reveal information, AND * - this commit does have reveal information, AND * - the reveal & commit information are matching. * * If all the above are true, then we are interested in this new commit * for its reveal information. */ if (!saved_commit) { log_debug(LD_DIR, "SR: Ignoring commit first seen in reveal phase."); goto ignore; } if (!commitments_are_the_same(commit, saved_commit)) { log_warn(LD_DIR, "SR: Commit from authority %s is different from " "previous commit in our state (voter: %s)", sr_commit_get_rsa_fpr(commit), hex_str(voter_key, DIGEST_LEN)); goto ignore; } if (commit_has_reveal_value(saved_commit)) { log_debug(LD_DIR, "SR: Ignoring commit with known reveal info."); goto ignore; } if (!commit_has_reveal_value(commit)) { log_debug(LD_DIR, "SR: Ignoring commit without reveal value."); goto ignore; } if (verify_commit_and_reveal(commit) < 0) { log_warn(LD_BUG, "SR: Commit from authority %s has an invalid " "reveal value. (voter: %s)", sr_commit_get_rsa_fpr(commit), hex_str(voter_key, DIGEST_LEN)); goto ignore; } break; default: tor_assert(0); } return 1; ignore: return 0; }
/* * Python-style long strings. Any bytes are allowed except three * quotes in a row ("""). C-style escapes are also supported. * * Right now this just takes the C-style escaped version, which can't * contain """ bytes anyway, but it's a little worse output than it * needs to be. */ std::string escaped_long(const StringData* sd) { return folly::format("\"\"{}\"\"", escaped(sd)).str(); }
void GUITestTeamcityLogger::testStarted(const QString& testName) { teamcityLog.trace(QString("##teamcity[testStarted name='%1']").arg(escaped(testName))); }
void GUITestTeamcityLogger::testIgnored(const QString& testName, const QString& ignoreReason) { teamcityLog.trace(QString("##teamcity[testIgnored name='%1' message='%2']").arg(escaped(testName), escaped(ignoreReason))); }
/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>, * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the * encrypted introduction points to the newly allocated * *<b>intro_points_encrypted_out</b>, their encrypted size to * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor * to *<b>encoded_size_out</b>, and a pointer to the possibly next * descriptor to *<b>next_out</b>; return 0 for success (including validation) * and -1 for failure. * * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should * be strict about time formats. */ int rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, char *desc_id_out, char **intro_points_encrypted_out, size_t *intro_points_encrypted_size_out, size_t *encoded_size_out, const char **next_out, const char *desc, int as_hsdir) { rend_service_descriptor_t *result = tor_malloc_zero(sizeof(rend_service_descriptor_t)); char desc_hash[DIGEST_LEN]; const char *eos; smartlist_t *tokens = smartlist_new(); directory_token_t *tok; char secret_id_part[DIGEST_LEN]; int i, version, num_ok=1; smartlist_t *versions; char public_key_hash[DIGEST_LEN]; char test_desc_id[DIGEST_LEN]; memarea_t *area = NULL; const int strict_time_fmt = as_hsdir; tor_assert(desc); /* Check if desc starts correctly. */ if (strcmpstart(desc, "rendezvous-service-descriptor ")) { log_info(LD_REND, "Descriptor does not start correctly."); goto err; } /* Compute descriptor hash for later validation. */ if (router_get_hash_impl(desc, strlen(desc), desc_hash, "rendezvous-service-descriptor ", "\nsignature", '\n', DIGEST_SHA1) < 0) { log_warn(LD_REND, "Couldn't compute descriptor hash."); goto err; } /* Determine end of string. */ eos = strstr(desc, "\nrendezvous-service-descriptor "); if (!eos) eos = desc + strlen(desc); else eos = eos + 1; /* Check length. */ if (eos-desc > REND_DESC_MAX_SIZE) { /* XXXX+ If we are parsing this descriptor as a server, this * should be a protocol warning. */ log_warn(LD_REND, "Descriptor length is %d which exceeds " "maximum rendezvous descriptor size of %d bytes.", (int)(eos-desc), REND_DESC_MAX_SIZE); goto err; } /* Tokenize descriptor. */ area = memarea_new(); if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) { log_warn(LD_REND, "Error tokenizing descriptor."); goto err; } /* Set next to next descriptor, if available. */ *next_out = eos; /* Set length of encoded descriptor. */ *encoded_size_out = eos - desc; /* Check min allowed length of token list. */ if (smartlist_len(tokens) < 7) { log_warn(LD_REND, "Impossibly short descriptor."); goto err; } /* Parse base32-encoded descriptor ID. */ tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR); tor_assert(tok == smartlist_get(tokens, 0)); tor_assert(tok->n_args == 1); if (!rend_valid_descriptor_id(tok->args[0])) { log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]); goto err; } if (base32_decode(desc_id_out, DIGEST_LEN, tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) { log_warn(LD_REND, "Descriptor ID contains illegal characters: %s", tok->args[0]); goto err; } /* Parse descriptor version. */ tok = find_by_keyword(tokens, R_VERSION); tor_assert(tok->n_args == 1); result->version = (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL); if (result->version != 2 || !num_ok) { /* If it's <2, it shouldn't be under this format. If the number * is greater than 2, we bumped it because we broke backward * compatibility. See how version numbers in our other formats * work. */ log_warn(LD_REND, "Unrecognized descriptor version: %s", escaped(tok->args[0])); goto err; } /* Parse public key. */ tok = find_by_keyword(tokens, R_PERMANENT_KEY); result->pk = tok->key; tok->key = NULL; /* Prevent free */ /* Parse secret ID part. */ tok = find_by_keyword(tokens, R_SECRET_ID_PART); tor_assert(tok->n_args == 1); if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 || strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) { log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]); goto err; } if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) { log_warn(LD_REND, "Secret ID part contains illegal characters: %s", tok->args[0]); goto err; } /* Parse publication time -- up-to-date check is done when storing the * descriptor. */ tok = find_by_keyword(tokens, R_PUBLICATION_TIME); tor_assert(tok->n_args == 1); if (parse_iso_time_(tok->args[0], &result->timestamp, strict_time_fmt, 0) < 0) { log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]); goto err; } /* Parse protocol versions. */ tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS); tor_assert(tok->n_args == 1); versions = smartlist_new(); smartlist_split_string(versions, tok->args[0], ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); for (i = 0; i < smartlist_len(versions); i++) { version = (int) tor_parse_long(smartlist_get(versions, i), 10, 0, INT_MAX, &num_ok, NULL); if (!num_ok) /* It's a string; let's ignore it. */ continue; if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH) /* Avoid undefined left-shift behaviour. */ continue; result->protocols |= 1 << version; } SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp)); smartlist_free(versions); /* Parse encrypted introduction points. Don't verify. */ tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS); if (tok) { if (strcmp(tok->object_type, "MESSAGE")) { log_warn(LD_DIR, "Bad object type: introduction points should be of " "type MESSAGE"); goto err; } *intro_points_encrypted_out = tor_memdup(tok->object_body, tok->object_size); *intro_points_encrypted_size_out = tok->object_size; } else { *intro_points_encrypted_out = NULL; *intro_points_encrypted_size_out = 0; } /* Parse and verify signature. */ tok = find_by_keyword(tokens, R_SIGNATURE); if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0, "v2 rendezvous service descriptor") < 0) goto err; /* Verify that descriptor ID belongs to public key and secret ID part. */ if (crypto_pk_get_digest(result->pk, public_key_hash) < 0) { log_warn(LD_REND, "Unable to compute rend descriptor public key digest"); goto err; } rend_get_descriptor_id_bytes(test_desc_id, public_key_hash, secret_id_part); if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) { log_warn(LD_REND, "Parsed descriptor ID does not match " "computed descriptor ID."); goto err; } goto done; err: rend_service_descriptor_free(result); result = NULL; done: if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) memarea_drop_all(area); *parsed_out = result; if (result) return 0; return -1; }
/* Configure a service using the given options in line_ and options. This is * called for any service regardless of its version which means that all * directives in this function are generic to any service version. This * function will also check the validity of the service directory path. * * The line_ must be pointing to the directive directly after a * HiddenServiceDir. That way, when hitting the next HiddenServiceDir line or * reaching the end of the list of lines, we know that we have to stop looking * for more options. * * Return 0 on success else -1. */ static int config_generic_service(const config_line_t *line_, const or_options_t *options, hs_service_t *service) { int dir_seen = 0; const config_line_t *line; hs_service_config_t *config; /* If this is set, we've seen a duplicate of this option. Keep the string * so we can log the directive. */ const char *dup_opt_seen = NULL; /* These variables will tell us if we ever have duplicate. */ int have_version = 0, have_allow_unknown_ports = 0; int have_dir_group_read = 0, have_max_streams = 0; int have_max_streams_close = 0; tor_assert(line_); tor_assert(options); tor_assert(service); /* Makes thing easier. */ config = &service->config; /* The first line starts with HiddenServiceDir so we consider what's next is * the configuration of the service. */ for (line = line_; line ; line = line->next) { int ok = 0; /* This indicate that we have a new service to configure. */ if (!strcasecmp(line->key, "HiddenServiceDir")) { /* This function only configures one service at a time so if we've * already seen one, stop right now. */ if (dir_seen) { break; } /* Ok, we've seen one and we are about to configure it. */ dir_seen = 1; config->directory_path = tor_strdup(line->value); log_info(LD_CONFIG, "HiddenServiceDir=%s. Configuring...", escaped(config->directory_path)); continue; } if (BUG(!dir_seen)) { goto err; } /* Version of the service. */ if (!strcasecmp(line->key, "HiddenServiceVersion")) { service->config.version = (uint32_t) helper_parse_uint64(line->key, line->value, HS_VERSION_MIN, HS_VERSION_MAX, &ok); if (!ok || have_version) { if (have_version) dup_opt_seen = line->key; goto err; } have_version = service->config.hs_version_explicitly_set = 1; continue; } /* Virtual port. */ if (!strcasecmp(line->key, "HiddenServicePort")) { char *err_msg = NULL; /* XXX: Can we rename this? */ rend_service_port_config_t *portcfg = rend_service_parse_port_config(line->value, " ", &err_msg); if (!portcfg) { if (err_msg) { log_warn(LD_CONFIG, "%s", err_msg); } tor_free(err_msg); goto err; } tor_assert(!err_msg); smartlist_add(config->ports, portcfg); log_info(LD_CONFIG, "HiddenServicePort=%s for %s", line->value, escaped(config->directory_path)); continue; } /* Do we allow unknown ports. */ if (!strcasecmp(line->key, "HiddenServiceAllowUnknownPorts")) { config->allow_unknown_ports = (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok); if (!ok || have_allow_unknown_ports) { if (have_allow_unknown_ports) dup_opt_seen = line->key; goto err; } have_allow_unknown_ports = 1; continue; } /* Directory group readable. */ if (!strcasecmp(line->key, "HiddenServiceDirGroupReadable")) { config->dir_group_readable = (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok); if (!ok || have_dir_group_read) { if (have_dir_group_read) dup_opt_seen = line->key; goto err; } have_dir_group_read = 1; continue; } /* Maximum streams per circuit. */ if (!strcasecmp(line->key, "HiddenServiceMaxStreams")) { config->max_streams_per_rdv_circuit = helper_parse_uint64(line->key, line->value, 0, HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT, &ok); if (!ok || have_max_streams) { if (have_max_streams) dup_opt_seen = line->key; goto err; } have_max_streams = 1; continue; } /* Maximum amount of streams before we close the circuit. */ if (!strcasecmp(line->key, "HiddenServiceMaxStreamsCloseCircuit")) { config->max_streams_close_circuit = (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok); if (!ok || have_max_streams_close) { if (have_max_streams_close) dup_opt_seen = line->key; goto err; } have_max_streams_close = 1; continue; } } /* Check if we are configured in non anonymous mode meaning every service * becomes a single onion service. */ if (rend_service_non_anonymous_mode_enabled(options)) { config->is_single_onion = 1; /* We will add support for IPv6-only v3 single onion services in a future * Tor version. This won't catch "ReachableAddresses reject *4", but that * option doesn't work anyway. */ if (options->ClientUseIPv4 == 0 && config->version == HS_VERSION_THREE) { log_warn(LD_CONFIG, "IPv6-only v3 single onion services are not " "supported. Set HiddenServiceSingleHopMode 0 and " "HiddenServiceNonAnonymousMode 0, or set ClientUseIPv4 1."); goto err; } } /* Success */ return 0; err: if (dup_opt_seen) { log_warn(LD_CONFIG, "Duplicate directive %s.", dup_opt_seen); } return -1; }
/** Parse the encoded introduction points in <b>intro_points_encoded</b> of * length <b>intro_points_encoded_size</b> and write the result to the * descriptor in <b>parsed</b>; return the number of successfully parsed * introduction points or -1 in case of a failure. */ int rend_parse_introduction_points(rend_service_descriptor_t *parsed, const char *intro_points_encoded, size_t intro_points_encoded_size) { const char *current_ipo, *end_of_intro_points; smartlist_t *tokens = NULL; directory_token_t *tok; rend_intro_point_t *intro; extend_info_t *info; int result, num_ok=1; memarea_t *area = NULL; tor_assert(parsed); /** Function may only be invoked once. */ tor_assert(!parsed->intro_nodes); if (!intro_points_encoded || intro_points_encoded_size == 0) { log_warn(LD_REND, "Empty or zero size introduction point list"); goto err; } /* Consider one intro point after the other. */ current_ipo = intro_points_encoded; end_of_intro_points = intro_points_encoded + intro_points_encoded_size; tokens = smartlist_new(); parsed->intro_nodes = smartlist_new(); area = memarea_new(); while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo, "introduction-point ")) { /* Determine end of string. */ const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo, "\nintroduction-point "); if (!eos) eos = end_of_intro_points; else eos = eos+1; tor_assert(eos <= intro_points_encoded+intro_points_encoded_size); /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) { log_warn(LD_REND, "Error tokenizing introduction point"); goto err; } /* Advance to next introduction point, if available. */ current_ipo = eos; /* Check minimum allowed length of introduction point. */ if (smartlist_len(tokens) < 5) { log_warn(LD_REND, "Impossibly short introduction point."); goto err; } /* Allocate new intro point and extend info. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); /* Parse identifier. */ tok = find_by_keyword(tokens, R_IPO_IDENTIFIER); if (base32_decode(info->identity_digest, DIGEST_LEN, tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) { log_warn(LD_REND, "Identity digest contains illegal characters: %s", tok->args[0]); rend_intro_point_free(intro); goto err; } /* Write identifier to nickname. */ info->nickname[0] = '$'; base16_encode(info->nickname + 1, sizeof(info->nickname) - 1, info->identity_digest, DIGEST_LEN); /* Parse IP address. */ tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS); if (tor_addr_parse(&info->addr, tok->args[0])<0) { log_warn(LD_REND, "Could not parse introduction point address."); rend_intro_point_free(intro); goto err; } if (tor_addr_family(&info->addr) != AF_INET) { log_warn(LD_REND, "Introduction point address was not ipv4."); rend_intro_point_free(intro); goto err; } /* Parse onion port. */ tok = find_by_keyword(tokens, R_IPO_ONION_PORT); info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535, &num_ok,NULL); if (!info->port || !num_ok) { log_warn(LD_REND, "Introduction point onion port %s is invalid", escaped(tok->args[0])); rend_intro_point_free(intro); goto err; } /* Parse onion key. */ tok = find_by_keyword(tokens, R_IPO_ONION_KEY); if (!crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_REND, "Introduction point's onion key had invalid exponent."); rend_intro_point_free(intro); goto err; } info->onion_key = tok->key; tok->key = NULL; /* Prevent free */ /* Parse service key. */ tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY); if (!crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_REND, "Introduction point key had invalid exponent."); rend_intro_point_free(intro); goto err; } intro->intro_key = tok->key; tok->key = NULL; /* Prevent free */ /* Add extend info to list of introduction points. */ smartlist_add(parsed->intro_nodes, intro); } result = smartlist_len(parsed->intro_nodes); goto done; err: result = -1; done: /* Free tokens and clear token list. */ if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) memarea_drop_all(area); return result; }
pgsOperand pgsExecute::eval(pgsVarMap &vars) const { // Copy statement locally wxString stmt(m_query); // Build regular expressions wxRegEx identifier(wxT("([^\\])(@[a-zA-Z0-9_#@]+)")); wxRegEx escaped(wxT("\\\\(@|\\\\)")); // Backslash followed by @ or backslash wxASSERT(identifier.IsValid() && escaped.IsValid()); // Replace variables in statement while (identifier.Matches(stmt)) { wxString var = identifier.GetMatch(stmt, 2); wxString chr = identifier.GetMatch(stmt, 1); if (vars.find(var) != vars.end()) { wxString res = vars[var]->eval(vars)->value(); identifier.ReplaceFirst(&stmt, chr + pgsUtilities::escape_quotes(res)); } else { identifier.ReplaceFirst(&stmt, chr + wxT("\\\\") + var); } } escaped.ReplaceAll(&stmt, wxT("\\1")); // Perform operations only if we have a valid connection if (m_app != 0 && m_app->connection() != 0 && !m_app->TestDestroy()) { pgQueryThread thread(m_app->connection(), stmt); if (thread.Create() == wxTHREAD_NO_ERROR) { if (thread.Run() == wxTHREAD_NO_ERROR) { while (true) { if (m_app->TestDestroy()) // wxThread::TestDestroy() { thread.Delete(); break; } else if (thread.IsRunning()) { m_app->Yield(); m_app->Sleep(20); } else { thread.Wait(); break; } } if (thread.ReturnCode() != PGRES_COMMAND_OK && thread.ReturnCode() != PGRES_TUPLES_OK) { if (m_cout != 0) { m_app->LockOutput(); (*m_cout) << PGSOUTWARNING; wxString message(stmt + wxT("\n") + thread .GetMessagesAndClear().Strip(wxString::both)); wxRegEx multilf(wxT("(\n)+")); multilf.ReplaceAll(&message, wxT("\n")); message.Replace(wxT("\n"), wxT("\n") + generate_spaces(PGSOUTWARNING.Length())); (*m_cout) << message << wxT("\n"); m_app->UnlockOutput(); } } else if (!m_app->TestDestroy()) { if (m_cout != 0) { m_app->LockOutput(); (*m_cout) << PGSOUTQUERY; wxString message(thread.GetMessagesAndClear() .Strip(wxString::both)); if (!message.IsEmpty()) message = stmt + wxT("\n") + message; else message = stmt; wxRegEx multilf(wxT("(\n)+")); multilf.ReplaceAll(&message, wxT("\n")); message.Replace(wxT("\n"), wxT("\n") + generate_spaces(PGSOUTQUERY.Length())); (*m_cout) << message << wxT("\n"); m_app->UnlockOutput(); } pgsRecord *rec = 0; if (thread.DataValid()) { pgSet *set = thread.DataSet(); set->MoveFirst(); rec = pnew pgsRecord(set->NumCols()); wxArrayLong columns_int; // List of columns that contain integers wxArrayLong columns_real; // List of columns that contain reals for (long i = 0; i < set->NumCols(); i++) { rec->set_column_name(i, set->ColName(i)); wxString col_type = set->ColType(i); if (!col_type.CmpNoCase(wxT("bigint")) || !col_type.CmpNoCase(wxT("smallint")) || !col_type.CmpNoCase(wxT("integer"))) { columns_int.Add(i); } else if (!col_type.CmpNoCase(wxT("real")) || !col_type.CmpNoCase(wxT("double precision")) || !col_type.CmpNoCase(wxT("money")) || !col_type.CmpNoCase(wxT("numeric"))) { columns_real.Add(i); } } size_t line = 0; while (!set->Eof()) { for (long i = 0; i < set->NumCols(); i++) { wxString value = set->GetVal(i); if (columns_int.Index(i) != wxNOT_FOUND && pgsNumber::num_type(value) == pgsNumber::pgsTInt) { rec->insert(line, i, pnew pgsNumber(value, pgsInt)); } else if (columns_real.Index(i) != wxNOT_FOUND && pgsNumber::num_type(value) == pgsNumber::pgsTReal) { rec->insert(line, i, pnew pgsNumber(value, pgsReal)); } else { rec->insert(line, i, pnew pgsString(value)); } } set->MoveNext(); ++line; } } else { rec = pnew pgsRecord(1); rec->insert(0, 0, pnew pgsNumber(wxT("1"))); } return rec; } } else { wxLogError(wxT("PGSCRIPT: Cannot run query thread for the query:\n%s"), m_query.c_str()); } } else { wxLogError(wxT("PGSCRIPT: Cannot create query thread for the query:\n%s"), m_query.c_str()); } } // This must return a record whatever happens return pnew pgsRecord(1); }
node gettoken(){ char *p = cur.text; if (*p == '\'') { char c; node token; advance(); if (cur.text == cur.eot) { fatal("file ends in character constant"); } if (*cur.text == '\\') { advance(); if (cur.text == cur.eot) { fatal("file ends in character constant"); } c = escaped(*cur.text); } else c = *cur.text; advance(); if (cur.text == cur.eot) fatal("file ends in character constant"); if (*cur.text != '\'') { fatal("character constant not terminated"); } advance(); token = newnode (CHAR_CONST,char_const_tag); token->body.char_const.contents = c; return token; } if (*p == '"') { char *s; node token; advance(); s = cur.text; while (TRUE) { if (cur.text == cur.eot) fatal("file ends before string"); if (cur.text[0]=='"') break; if (*cur.text == '\\') { advance(); if (cur.text == cur.eot) fatal("file ends before string"); } advance(); } token = newnode(STRING_CONST,string_const_tag); token->body.unique_string.characters = strnperm(s,cur.text-s); /* observe that escaped character sequences such as \n are not simplified here */ advance(); return token; } if (*p == ',' || *p == '.') { advance(); } else { bool digitssofar = TRUE; while (TRUE) { if (!isdigit((int)*cur.text)) digitssofar = FALSE; advance(); if (cur.text == cur.eot) break; if (*cur.text == '.' && digitssofar) continue; if (istoken(*cur.text)) continue; break; } if (integerq(p,cur.text-p)) { return IntegerN(p,cur.text-p); } if (doubleq(p,cur.text-p)) { return DoubleN(p,cur.text-p); } } return UniqueStringN(p,cur.text-p); }
bool csstidy::is_token(string& istring,const int i) { return (in_str_array(tokens,istring[i]) && !escaped(istring,i)); }
void GUITestTeamcityLogger::teamCityLogResult(const QString &testName, const QString &testResult, qint64 testTimeMicros) { if (testFailed(testResult)) { teamcityLog.trace(QString("##teamcity[testFailed name='%1' message='%2' details='%2' duration='%3']").arg(escaped(testName), escaped(testResult), QString::number(testTimeMicros))); } teamcityLog.trace(QString("##teamcity[testFinished name='%1' duration='%2']").arg(escaped(testName), QString::number(testTimeMicros))); }
void sexpr::display_atom(std::ostream & out) const { switch (get_kind()) { case sexpr::COMPOSITE: UNREACHABLE(); case sexpr::NUMERAL: out << static_cast<sexpr_numeral const *>(this)->m_val; break; case sexpr::BV_NUMERAL: { out << '#'; unsigned bv_size = static_cast<sexpr_bv const *>(this)->m_size; rational val = static_cast<sexpr_bv const *>(this)->m_val; sbuffer<char> buf; unsigned sz = 0; if (bv_size % 4 == 0) { out << 'x'; while (val.is_pos()) { rational c = val % rational(16); val = div(val, rational(16)); SASSERT(rational(0) <= c && c < rational(16)); if (c <= rational(9)) buf.push_back('0' + c.get_unsigned()); else buf.push_back('a' + (c.get_unsigned() - 10)); sz+=4; } while (sz < bv_size) { buf.push_back('0'); sz+=4; } } else { out << 'b'; while (val.is_pos()) { rational c = val % rational(2); val = div(val, rational(2)); SASSERT(rational(0) <= c && c < rational(2)); if (c.is_zero()) buf.push_back('0'); else buf.push_back('1'); sz += 1; } while (sz < bv_size) { buf.push_back('0'); sz += 1; } } std::reverse(buf.begin(), buf.end()); buf.push_back(0); out << buf.c_ptr(); break; } case sexpr::STRING: out << "\"" << escaped(static_cast<sexpr_string const *>(this)->m_val.c_str()) << "\""; break; case sexpr::SYMBOL: case sexpr::KEYWORD: out << static_cast<sexpr_symbol const *>(this)->m_val; break; default: UNREACHABLE(); } }
void tst_escaped() { std::cout << "[" << escaped("\"hello\"\"world\"\n\n") << "]\n"; std::cout << "[" << escaped("\"hello\"\nworld\"\n\n\n", true) << "]\n"; std::cout << "[" << escaped("\"hello\"\nworld\"\n", true) << "]\n"; std::cout << "[" << escaped("\"hello\"\nworld\"", true) << "]\n"; std::cout << "[" << escaped("\"hello\"\n\"world\"\n\n") << "]\n"; std::cout << "[" << escaped("\n\n\n", true) << "]\n"; std::cout << "[" << escaped("\n\n\n") << "]\n"; std::cout << "[" << escaped("\n", true) << "]\n"; std::cout << "[" << escaped("\n") << "]\n"; std::cout << "[" << escaped("", true) << "]\n"; std::cout << "[" << escaped("") << "]\n"; std::cout << "[" << escaped(0, true) << "]\n"; std::cout << "[" << escaped(0) << "]\n"; }
NS_IMETHODIMP nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest, nsISupports *aCtxt, nsIDirIndex *aIndex) { nsresult rv; if (!aIndex) return NS_ERROR_NULL_POINTER; nsCString pushBuffer; pushBuffer.AppendLiteral("<tr"); // We don't know the file's character set yet, so retrieve the raw bytes // which will be decoded by the HTML parser. nsXPIDLCString loc; aIndex->GetLocation(getter_Copies(loc)); // Adjust the length in case unescaping shortened the string. loc.Truncate(nsUnescapeCount(loc.BeginWriting())); if (loc.First() == char16_t('.')) pushBuffer.AppendLiteral(" class=\"hidden-object\""); pushBuffer.AppendLiteral(">\n <td sortable-data=\""); // The sort key is the name of the item, prepended by either 0, 1 or 2 // in order to group items. uint32_t type; aIndex->GetType(&type); switch (type) { case nsIDirIndex::TYPE_SYMLINK: pushBuffer.Append('0'); break; case nsIDirIndex::TYPE_DIRECTORY: pushBuffer.Append('1'); break; default: pushBuffer.Append('2'); break; } nsAdoptingCString escaped(nsEscapeHTML(loc)); pushBuffer.Append(escaped); pushBuffer.AppendLiteral("\"><table class=\"ellipsis\"><tbody><tr><td><a class=\""); switch (type) { case nsIDirIndex::TYPE_DIRECTORY: pushBuffer.AppendLiteral("dir"); break; case nsIDirIndex::TYPE_SYMLINK: pushBuffer.AppendLiteral("symlink"); break; default: pushBuffer.AppendLiteral("file"); break; } pushBuffer.AppendLiteral("\" href=\""); // need to escape links nsAutoCString locEscaped; // Adding trailing slash helps to recognize whether the URL points to a file // or a directory (bug #214405). if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) { loc.Append('/'); } // now minimally re-escape the location... uint32_t escFlags; // for some protocols, we expect the location to be absolute. // if so, and if the location indeed appears to be a valid URI, then go // ahead and treat it like one. nsAutoCString scheme; if (mExpectAbsLoc && NS_SUCCEEDED(net_ExtractURLScheme(loc, scheme))) { // escape as absolute escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal; } else { // escape as relative // esc_Directory is needed because directories have a trailing slash. // Without it, the trailing '/' will be escaped, and links from within // that directory will be incorrect escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory; } NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped); // esc_Directory does not escape the semicolons, so if a filename // contains semicolons we need to manually escape them. // This replacement should be removed in bug #473280 locEscaped.ReplaceSubstring(";", "%3b"); nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get())); pushBuffer.Append(htmlEscapedURL); pushBuffer.AppendLiteral("\">"); if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) { pushBuffer.AppendLiteral("<img src=\"moz-icon://"); int32_t lastDot = locEscaped.RFindChar('.'); if (lastDot != kNotFound) { locEscaped.Cut(0, lastDot); nsAdoptingCString htmlFileExt(nsEscapeHTML(locEscaped.get())); pushBuffer.Append(htmlFileExt); } else { pushBuffer.AppendLiteral("unknown"); } pushBuffer.AppendLiteral("?size=16\" alt=\""); nsXPIDLString altText; rv = mBundle->GetStringFromName(MOZ_UTF16("DirFileLabel"), getter_Copies(altText)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(altText, pushBuffer); pushBuffer.AppendLiteral("\">"); } pushBuffer.Append(escaped); pushBuffer.AppendLiteral("</a></td></tr></tbody></table></td>\n <td"); if (type == nsIDirIndex::TYPE_DIRECTORY || type == nsIDirIndex::TYPE_SYMLINK) { pushBuffer.Append('>'); } else { int64_t size; aIndex->GetSize(&size); if (uint64_t(size) != UINT64_MAX) { pushBuffer.AppendLiteral(" sortable-data=\""); pushBuffer.AppendInt(size); pushBuffer.AppendLiteral("\">"); nsAutoCString sizeString; FormatSizeString(size, sizeString); pushBuffer.Append(sizeString); } else { pushBuffer.Append('>'); } } pushBuffer.AppendLiteral("</td>\n <td"); PRTime t; aIndex->GetLastModified(&t); if (t == -1LL) { pushBuffer.AppendLiteral("></td>\n <td>"); } else { pushBuffer.AppendLiteral(" sortable-data=\""); pushBuffer.AppendInt(static_cast<int64_t>(t)); pushBuffer.AppendLiteral("\">"); nsAutoString formatted; mDateTime->FormatPRTime(nullptr, kDateFormatShort, kTimeFormatNone, t, formatted); AppendNonAsciiToNCR(formatted, pushBuffer); pushBuffer.AppendLiteral("</td>\n <td>"); mDateTime->FormatPRTime(nullptr, kDateFormatNone, kTimeFormatSeconds, t, formatted); // use NCR to show date in any doc charset AppendNonAsciiToNCR(formatted, pushBuffer); } pushBuffer.AppendLiteral("</td>\n</tr>"); return SendToListener(aRequest, aCtxt, pushBuffer); }
void print_instr(Output& out, const FuncInfo& finfo, PC pc) { auto const startPc = pc; auto rel_label = [&] (Offset off) { auto const tgt = startPc - finfo.unit->at(0) + off; return jmp_label(finfo, tgt); }; auto print_switch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const off = decode<Offset>(pc); FTRACE(1, "sw label: {}\n", off); out.fmt("{}{}", i != 0 ? " " : "", rel_label(off)); } out.fmt(">"); }; auto print_sswitch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const strId = decode<Id>(pc); auto const offset = decode<Offset>(pc); out.fmt("{}{}:{}", i != 0 ? " " : "", strId == -1 ? "-" : escaped(finfo.unit->lookupLitstrId(strId)), rel_label(offset) ); } out.fmt(">"); }; auto print_itertab = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const kind = static_cast<IterKind>(decode<int32_t>(pc)); auto const id = decode<int32_t>(pc); auto const kindStr = [&]() -> const char* { switch (kind) { case KindOfIter: return "(Iter)"; case KindOfMIter: return "(MIter)"; case KindOfCIter: return "(CIter)"; } not_reached(); }(); out.fmt("{}{} {}", i != 0 ? ", " : "", kindStr, id); } out.fmt(">"); }; auto print_stringvec = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = uint32_t{0}; i < vecLen; ++i) { auto const str = finfo.unit->lookupLitstrId(decode<int32_t>(pc)); out.fmt("{}{}", i != 0 ? " " : "", escaped(str)); } out.fmt(">"); }; #define IMM_BLA print_switch(); #define IMM_SLA print_sswitch(); #define IMM_ILA print_itertab(); #define IMM_IVA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_I64A out.fmt(" {}", decode<int64_t>(pc)); #define IMM_LA out.fmt(" {}", loc_name(finfo, decodeVariableSizeImm(&pc))); #define IMM_IA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_DA out.fmt(" {}", decode<double>(pc)); #define IMM_SA out.fmt(" {}", \ escaped(finfo.unit->lookupLitstrId(decode<Id>(pc)))); #define IMM_RATA out.fmt(" {}", show(decodeRAT(finfo.unit, pc))); #define IMM_AA out.fmt(" @A_{}", decode<Id>(pc)); #define IMM_BA out.fmt(" {}", rel_label(decode<Offset>(pc))); #define IMM_OA(ty) out.fmt(" {}", \ subopToName(static_cast<ty>(decode<uint8_t>(pc)))); #define IMM_VSA print_stringvec(); #define IMM_KA out.fmt(" {}", show(decode_member_key(pc, finfo.unit))); #define IMM_NA #define IMM_ONE(x) IMM_##x #define IMM_TWO(x,y) IMM_ONE(x) IMM_ONE(y) #define IMM_THREE(x,y,z) IMM_TWO(x,y) IMM_ONE(z) #define IMM_FOUR(x,y,z,l) IMM_THREE(x,y,z) IMM_ONE(l) out.indent(); #define O(opcode, imms, ...) \ case Op::opcode: \ ++pc; \ out.fmt("{}", #opcode); \ IMM_##imms \ break; switch (peek_op(pc)) { OPCODES } #undef O assert(pc == startPc + instrLen(startPc)); #undef IMM_NA #undef IMM_ONE #undef IMM_TWO #undef IMM_THREE #undef IMM_FOUR #undef IMM_BLA #undef IMM_SLA #undef IMM_ILA #undef IMM_IVA #undef IMM_I64A #undef IMM_LA #undef IMM_IA #undef IMM_DA #undef IMM_SA #undef IMM_RATA #undef IMM_AA #undef IMM_BA #undef IMM_OA #undef IMM_VSA #undef IMM_KA out.nl(); }
void print_instr(Output& out, const FuncInfo& finfo, PC pc) { auto const startPc = pc; auto rel_label = [&] (Offset off) { auto const tgt = startPc - finfo.unit->at(0) + off; return jmp_label(finfo, tgt); }; auto print_minstr = [&] { auto const immVec = ImmVector::createFromStream(pc); pc += immVec.size() + sizeof(int32_t) + sizeof(int32_t); auto vec = immVec.vec(); auto const lcode = static_cast<LocationCode>(*vec++); out.fmt(" <{}", locationCodeString(lcode)); if (numLocationCodeImms(lcode)) { always_assert(numLocationCodeImms(lcode) == 1); out.fmt(":${}", loc_name(finfo, decodeVariableSizeImm(&vec))); } while (vec < pc) { auto const mcode = static_cast<MemberCode>(*vec++); out.fmt(" {}", memberCodeString(mcode)); auto const imm = [&] { return decodeMemberCodeImm(&vec, mcode); }; switch (memberCodeImmType(mcode)) { case MCodeImm::None: break; case MCodeImm::Local: out.fmt(":${}", loc_name(finfo, imm())); break; case MCodeImm::String: out.fmt(":{}", escaped(finfo.unit->lookupLitstrId(imm()))); break; case MCodeImm::Int: out.fmt(":{}", imm()); break; } } assert(vec == pc); out.fmt(">"); }; auto print_switch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const off = decode<Offset>(pc); FTRACE(1, "sw label: {}\n", off); out.fmt("{}{}", i != 0 ? " " : "", rel_label(off)); } out.fmt(">"); }; auto print_sswitch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const strId = decode<Id>(pc); auto const offset = decode<Offset>(pc); out.fmt("{}{}:{}", i != 0 ? " " : "", strId == -1 ? "-" : escaped(finfo.unit->lookupLitstrId(strId)), rel_label(offset) ); } out.fmt(">"); }; auto print_itertab = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const kind = static_cast<IterKind>(decode<int32_t>(pc)); auto const id = decode<int32_t>(pc); auto const kindStr = [&]() -> const char* { switch (kind) { case KindOfIter: return "(Iter)"; case KindOfMIter: return "(MIter)"; case KindOfCIter: return "(CIter)"; } not_reached(); }(); out.fmt("{}{} {}", i != 0 ? ", " : "", kindStr, id); } out.fmt(">"); }; auto print_stringvec = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = uint32_t{0}; i < vecLen; ++i) { auto const str = finfo.unit->lookupLitstrId(decode<int32_t>(pc)); out.fmt("{}{}", i != 0 ? " " : "", escaped(str)); } out.fmt(">"); }; #define IMM_MA print_minstr(); #define IMM_BLA print_switch(); #define IMM_SLA print_sswitch(); #define IMM_ILA print_itertab(); #define IMM_IVA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_I64A out.fmt(" {}", decode<int64_t>(pc)); #define IMM_LA out.fmt(" ${}", loc_name(finfo, decodeVariableSizeImm(&pc))); #define IMM_IA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_DA out.fmt(" {}", decode<double>(pc)); #define IMM_SA out.fmt(" {}", \ escaped(finfo.unit->lookupLitstrId(decode<Id>(pc)))); #define IMM_AA out.fmt(" @A_{}", decode<Id>(pc)); #define IMM_BA out.fmt(" {}", rel_label(decode<Offset>(pc))); #define IMM_OA(ty) out.fmt(" {}", \ subopToName(static_cast<ty>(decode<uint8_t>(pc)))); #define IMM_VSA print_stringvec(); #define IMM_NA #define IMM_ONE(x) IMM_##x #define IMM_TWO(x,y) IMM_ONE(x) IMM_ONE(y) #define IMM_THREE(x,y,z) IMM_TWO(x,y) IMM_ONE(z) #define IMM_FOUR(x,y,z,l) IMM_THREE(x,y,z) IMM_ONE(l) out.indent(); #define O(opcode, imms, ...) \ case Op::opcode: \ ++pc; \ out.fmt("{}", #opcode); \ IMM_##imms \ break; switch (*reinterpret_cast<const Op*>(pc)) { OPCODES } #undef O assert(pc == startPc + instrLen(reinterpret_cast<const Op*>(startPc))); #undef IMM_NA #undef IMM_ONE #undef IMM_TWO #undef IMM_THREE #undef IMM_FOUR #undef IMM_MA #undef IMM_BLA #undef IMM_SLA #undef IMM_ILA #undef IMM_IVA #undef IMM_I64A #undef IMM_LA #undef IMM_IA #undef IMM_DA #undef IMM_SA #undef IMM_AA #undef IMM_BA #undef IMM_OA #undef IMM_VSA out.nl(); }
/** * Read the measured bandwidth list <b>from_file</b>: * - store all the headers in <b>bw_file_headers</b>, * - apply bandwidth lines to the list of vote_routerstatus_t in * <b>routerstatuses</b>, * - cache bandwidth lines for dirserv_get_bandwidth_for_router(), * - expire old entries in the measured bandwidth cache, and * - store the DIGEST_SHA256 of the contents of the file in <b>digest_out</b>. * * Returns -1 on error, 0 otherwise. * * If the file can't be read, or is empty: * - <b>bw_file_headers</b> is empty, * - <b>routerstatuses</b> is not modified, * - the measured bandwidth cache is not modified, and * - <b>digest_out</b> is the zero-byte digest. * * Otherwise, if there is an error later in the file: * - <b>bw_file_headers</b> contains all the headers up to the error, * - <b>routerstatuses</b> is updated with all the relay lines up to the error, * - the measured bandwidth cache is updated with all the relay lines up to * the error, * - if the timestamp is valid and recent, old entries in the measured * bandwidth cache are expired, and * - <b>digest_out</b> is the digest up to the first read error (if any). * The digest is taken over all the readable file contents, even if the * file is outdated or unparseable. */ int dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses, smartlist_t *bw_file_headers, uint8_t *digest_out) { FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; time_t file_time, now; int ok; /* This flag will be 1 only when the first successful bw measurement line * has been encountered, so that measured_bw_line_parse don't give warnings * if there are additional header lines, as introduced in Bandwidth List spec * version 1.1.0 */ int line_is_after_headers = 0; int rv = -1; char *line = NULL; size_t n = 0; crypto_digest_t *digest = crypto_digest256_new(DIGEST_SHA256); if (fp == NULL) { log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s", from_file); goto err; } if (tor_getline(&line,&n,fp) <= 0) { log_warn(LD_DIRSERV, "Empty bandwidth file"); goto err; } /* If the line could be gotten, add it to the digest */ crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); if (!strlen(line) || line[strlen(line)-1] != '\n') { log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s", escaped(line)); /* Continue adding lines to the digest. */ goto continue_digest; } line[strlen(line)-1] = '\0'; file_time = (time_t)tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s", escaped(line)); goto continue_digest; } now = approx_time(); if ((now - file_time) > MAX_MEASUREMENT_AGE) { log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u", (unsigned)(time(NULL) - file_time)); goto continue_digest; } /* If timestamp was correct and bw_file_headers is not NULL, * add timestamp to bw_file_headers */ if (bw_file_headers) smartlist_add_asprintf(bw_file_headers, "timestamp=%lu", (unsigned long)file_time); if (routerstatuses) smartlist_sort(routerstatuses, compare_vote_routerstatus_entries); while (!feof(fp)) { measured_bw_line_t parsed_line; if (tor_getline(&line, &n, fp) >= 0) { crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); if (measured_bw_line_parse(&parsed_line, line, line_is_after_headers) != -1) { /* This condition will be true when the first complete valid bw line * has been encountered, which means the end of the header lines. */ line_is_after_headers = 1; /* Also cache the line for dirserv_get_bandwidth_for_router() */ dirserv_cache_measured_bw(&parsed_line, file_time); if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0) applied_lines++; /* if the terminator is found, it is the end of header lines, set the * flag but do not store anything */ } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) { line_is_after_headers = 1; /* if the line was not a correct relay line nor the terminator and * the end of the header lines has not been detected yet * and it is key_value and bw_file_headers did not reach the maximum * number of headers, * then assume this line is a header and add it to bw_file_headers */ } else if (bw_file_headers && (line_is_after_headers == 0) && string_is_key_value(LOG_DEBUG, line) && !strchr(line, ' ') && (smartlist_len(bw_file_headers) < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) { line[strlen(line)-1] = '\0'; smartlist_add_strdup(bw_file_headers, line); }; } } /* Now would be a nice time to clean the cache, too */ dirserv_expire_measured_bw_cache(now); log_info(LD_DIRSERV, "Bandwidth measurement file successfully read. " "Applied %d measurements.", applied_lines); rv = 0; continue_digest: /* Continue parsing lines to return the digest of the Bandwidth File. */ while (!feof(fp)) { if (tor_getline(&line, &n, fp) >= 0) { crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); } } err: if (line) { // we need to raw_free this buffer because we got it from tor_getdelim() raw_free(line); } if (fp) fclose(fp); if (digest_out) crypto_digest_get_digest(digest, (char *) digest_out, DIGEST256_LEN); crypto_digest_free(digest); return rv; }